Hibernate更新对象时关联实体重复问题求助
问题描述
我有Goods和Sizes两张表,多个Size可关联同一个Good,接口返回的JSON结构如下:
{ "id": 11, "title": "Model2", "sex": "WOMAN", "manufacturer": { "id": 1, "manufacturerName": "Ralf", "address": "Moscow", "telephone": "9-999-999-99-99" }, "manufacturerId": 1, "sizes": [ { "size": 35, "quantity": 5 }, { "size": 46, "quantity": 4 } ] }
当我尝试更新某个Good(比如添加或删除一个Size)时,所有Size都会重复,原本2个会变成4个:
"sizes": [ { "size": 30, "quantity": 2 }, { "size": 42, "quantity": 5 }, { "size": 41, "quantity": 2 }, { "size": 42, "quantity": 5 } ]
我的更新方法如下:
@Override public void saveGood(Good good) { Session session = entityManager.unwrap(Session.class); System.out.println(good); session.merge(good); //SaveOrUpdate substitute }
REST控制器路由:
@PatchMapping("/goods") public Good updateGood(@RequestBody Good good) { goodService.saveGood(good); return good; }
实体类关联配置:Good类:
@JsonManagedReference @OneToMany(cascade = CascadeType.ALL, mappedBy = "good")//Uni-directional reference to size array List<Size> sizes;
Size类:
@Column(name = "goodid", insertable = false, updatable = false) //Check else private int goodId; @JsonBackReference @ManyToOne(cascade = CascadeType.ALL) @JoinColumn(name = "goodId") Good good;
请问如何解决更新时关联Size实体重复的问题?
解决方案
1. 先清理旧关联,再替换为新数据
使用merge时,Hibernate会保留数据库中已存在的关联对象,同时添加传入的新对象,导致重复。需要先从数据库加载持久化状态的Good,清空现有Size关联后,再添加新的Size并维护双向关系:
@Override public void saveGood(Good good) { Session session = entityManager.unwrap(Session.class); // 加载数据库中当前的Good对象 Good persistedGood = session.get(Good.class, good.getId()); // 清空现有Size关联 persistedGood.getSizes().clear(); // 绑定新Size与持久化Good的双向关系 for (Size size : good.getSizes()) { size.setGood(persistedGood); persistedGood.getSizes().add(size); } session.merge(persistedGood); }
2. 调整级联策略,避免过度级联
当前@OneToMany和@ManyToOne都设置了CascadeType.ALL,会导致更新Good时所有关联Size被无差别级联操作。如果Size生命周期完全依赖Good,可保留核心级联类型,否则调整为:Good类修改:
@JsonManagedReference @OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "good") List<Size> sizes;
Size类修改:
@JsonBackReference @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}) @JoinColumn(name = "goodId") Good good;
3. 给Size添加唯一约束
在数据库层面,同一个Good下的尺码应该唯一,通过实体类注解添加组合唯一约束,从根源阻止重复数据:
@Entity @Table(uniqueConstraints = {@UniqueConstraint(columnNames = {"goodId", "size"})}) public class Size { // 其他字段定义 }
4. 严格维护双向关联关系
双向关联中,必须确保Size的good属性指向持久化状态的Good对象,而非传入的临时对象,否则Hibernate无法识别关联关系,会误判为新对象插入。
内容的提问来源于stack exchange,提问作者velovatik
相关产品推荐
相关产品推荐

