Hibernate/JPA Merge更新异常求助:关联瞬态对象报错
解决Hibernate merge时的瞬态对象异常问题
嘿,这个问题我之前也踩过类似的坑!咱们先把异常的本质搞清楚:not-null property references a transient value 意思是你的PVV对象里的p301KainInkaId是一个瞬态对象(没有被Hibernate管理的对象),但数据库里这个字段是not-null的,Hibernate不知道该怎么把这个瞬态的PVV和持久化的KainInka关联起来,所以抛了错。
核心问题:双向关联没维护完整
你的实体关联是双向的:KainInka(一对多)→ PVV,PVV(多对一)→ KainInka。Hibernate里,多对一的一方是关联的拥有端(因为你在KainInka的@OneToMany里用了mappedBy = "p301KainInkaId",把关联的控制权交给了PVV的@ManyToOne属性)。这意味着:
- 仅仅把PVV加到KainInka的
kainInkaPvvs列表里是不够的 - 必须同时给PVV设置
p301KainInkaId,指向那个已经存在的、持久化的KainInka对象
同样,PVV和PVT的双向关联也要这么做——给新的PVT设置p301KainInkaPvvId指向新创建的PVV。
正确的操作步骤(附代码示例)
假设你的kainInkaObj是从数据库加载的持久化对象(或者是之前merge返回的托管对象),正确的代码应该是这样:
// 1. 创建新的PVV对象,设置基础属性 TP301KainInkaPvv newPvv = new TP301KainInkaPvv(); // newPvv.setXXX(...) 这里设置PVV的其他业务属性 // 关键!给PVV设置反向关联,指向持久化的KainInka newPvv.setP301KainInkaId(kainInkaObj); // 2. 把PVV加到KainInka的列表里(维护主动端) List<TP301KainInkaPvv> pvvsList = kainInkaObj.getKainInkaPvvs(); if (pvvsList == null) { pvvsList = new ArrayList<>(); kainInkaObj.setKainInkaPvvs(pvvsList); } pvvsList.add(newPvv); // 3. 处理PVV下的新PVT对象,同样维护双向关联 TP301KainInkaPvt newPvt = new TP301KainInkaPvt(); // newPvt.setXXX(...) 设置PVT的业务属性 // 关键!给PVT设置反向关联,指向刚创建的PVV newPvt.setP301KainInkaPvvId(newPvv); List<TP301KainInkaPvt> pvtsList = newPvv.getKainInkaPvts(); if (pvtsList == null) { pvtsList = new ArrayList<>(); newPvv.setKainInkaPvts(pvtsList); } pvtsList.add(newPvt); // 4. 最后调用merge kainInkaDao.merge(kainInkaObj);
额外的几个注意点
- merge的行为要搞懂:merge是把瞬态对象的状态同步到持久化上下文里的对象。如果你的
kainInkaObj是从数据库load出来的,它本身就是托管状态,merge会直接更新它;如果是你自己new的,merge会先找数据库里有没有对应的记录,没有的话会创建新的。 - @OnDelete的作用:你加的
@OnDelete(action = OnDeleteAction.CASCADE)是数据库层面的级联删除(生成DDL时给外键加ON DELETE CASCADE),和Hibernate的CascadeType.ALL不是一回事——后者是会话级的操作级联(比如persist、merge时联动子对象),这个不影响当前的merge问题,但要确保两者的预期一致。 - 孤儿移除的生效条件:你设置了
orphanRemoval = true,这个会在你从KainInka的列表里移除PVV时自动删除PVV,但前提是你正确维护了双向关联。
按照这个方式调整代码,应该就能解决这个异常了!
内容的提问来源于stack exchange,提问作者info_tech
相关产品推荐
相关产品推荐

