Hibernate一对多关联执行save时出现冗余更新的原因咨询
为什么会出现冗余的更新语句?
兄弟,这个问题我碰到过好多次了,本质是JPA关联维护端的配置误区,我给你掰扯清楚:
1. 你的当前配置的核心问题
你在父实体A上用了@OneToMany(cascade=CascadeType.ALL) + @JoinColumn(name="TableA_Id",nullable=false),这种配置会让Hibernate误以为父表A是关联关系的维护端——但实际上,外键TableA_Id是在子表B里的,按照JPA规范,关联的维护端必须是拥有外键的那一方(也就是子实体B)。
2. Hibernate的执行流程解析
当你执行session.save(A)时,Hibernate的执行步骤是:
- 先插入父实体A,生成并获取它的主键ID;
- 接着插入两个子实体B,此时会把
TableA_Id设为A的ID(因为级联保存和@JoinColumn的配置); - 但由于Hibernate错误地认为A是维护端,它会额外执行两次更新语句,再次把B的
TableA_Id设置为同一个A的ID——这就是你看到的“冗余更新”,虽然结果正确,但完全没必要。
3. 正确的配置方式
要解决这个问题,需要把关联的维护端交还给子实体B,调整配置如下:
父实体A的配置
@OneToMany(mappedBy = "a", cascade = CascadeType.ALL) private List<B> bs = new ArrayList<>();
这里的mappedBy = "a"表示:关联关系由B类中的a字段来维护,A只是关联的“被维护端”。
子实体B的配置
@ManyToOne @JoinColumn(name = "TableA_Id", nullable = false) private A a;
这里的@JoinColumn明确指定了外键列,并且@ManyToOne标记了B是关联的维护端。
这样配置后,Hibernate会直接在插入B的时候就把TableA_Id设为A的ID,不会再执行冗余的更新语句,SQL会变成3条插入语句,没有多余的操作。
内容的提问来源于stack exchange,提问作者ChuckLeviton
相关产品推荐
相关产品推荐

