You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA无法删除单行数据问题及主键类型适配异常求助

问题分析与解决方案

看起来你遇到的问题主要来自两个关键错误:JPA主键生成注解误用,以及基本类型主键导致的实体状态判断异常。我来一步步帮你拆解和解决:

1. 核心问题:@Generated 注解写错了!

你的UserInformation和PersonalInfo实体中,主键的生成注解写成了@Generated,但JPA规范里的正确注解是@GeneratedValue!这个错误直接导致了后续所有异常:

  • 当id是int基本类型时,默认值为0,JPA会把这个0当作已存在的主键值去执行删除,而你的数据库主键是从1开始自增的,自然找不到对应数据,所以删除无效果也无报错;
  • 改成Integer包装类后,删除时你硬编码了正确的非null主键值,能匹配到数据所以删除成功,但插入时因为@Generated注解无效,JPA不会触发数据库的主键自增规则,反而尝试插入null(Integer默认值),触发了数据库的主键非空约束,导致插入失败。

2. 具体修复步骤

步骤1:修正主键生成注解

把UserInformation和PersonalInfo中的@Generated替换为@GeneratedValue,并针对PostgreSQL设置合适的自增策略:

// UserInformation 修正后
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
// PersonalInfo 修正后
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "info_id")
private Integer infoId;

注:PostgreSQL的自增主键通常用GenerationType.IDENTITY(对应数据库的serial类型),如果你的表用的是自定义序列,也可以用GenerationType.SEQUENCE并指定序列名称。

步骤2:坚持用包装类型作为主键

别再用int/long这类基本类型当主键:

  • 包装类型(Integer/Long)默认值是null,JPA能通过null主键判断这是新实体,会自动触发插入和主键自增;
  • 基本类型默认值为0,JPA会误以为这是一个已存在的实体(主键为0),尝试执行更新而非插入,这会引发各种不符合预期的行为。

步骤3:确保删除操作在事务中执行

Spring的@Service注解本身不会开启事务,建议在删除方法上添加@Transactional注解,保证操作能正确提交到数据库:

@Service
public class UserRegistrationService {
    @Autowired
    UserInformationRepository userInformationRepository;
    
    // ... 其他方法
    
    @Transactional
    public void deleteUserInformation(Integer userId) {
        // 推荐直接用deleteById,代码更简洁高效
        userInformationRepository.deleteById(userId);
    }
}

3. 额外检查项

  • 确认你的PostgreSQL表中,user_info.id和personal_info.info_id字段是serial或bigserial类型(支持自增);
  • 插入测试时,不要手动设置id值,完全交给JPA和数据库自动生成。

按照以上步骤修复后,插入和删除操作应该都能正常工作了。

内容的提问来源于stack exchange,提问作者ButtahNBred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:40