我正在开发Spring数据,JPA,Hibernate组合的Spring Boot应用程序。下面是我正在努力的方案,预期的行为是只更新一些子实体,而父实体被插入为新实体。Spring数据与Hibernate JPA仓库 - 坚持(SQL插入)父实体,但只更新嵌套的子实体
实体类
@Entity
public class A {
@Id
private long id;
@ManyToOne
@JoinColumn (name = "B_ID")
@Cascade ({ CascadeType.ALL })
private B b;
}
@Entity
@DynamicUpdate
public class B {
@Id
private long id;
@OneToMany (mappedBy = "b")
@Cascade ({ CascadeType.ALL })
private Set<A> as;
@ManyToOne
@JoinColumn (name = "C_ID")
@Cascade ({ CascadeType.ALL })
private C c;
}
@Entity
@DynamicUpdate
public class C {
@Id
private long id;
@OneToMany (mappedBy = "c")
@Cascade ({ CascadeType.ALL })
private Set<B> bs;
@ManyToOne
@JoinColumn (name = "D_ID")
@Cascade ({ CascadeType.ALL })
private D d;
@ManyToOne
@JoinColumn (name = "E_ID")
@Cascade ({ CascadeType.ALL })
private E e;
}
@Entity
@DynamicUpdate
public class D {
@Id
private long id;
@OneToMany (mappedBy = "d")
@Cascade ({ CascadeType.ALL })
private Set<C> cs;
}
@Entity
@DynamicUpdate
public class E {
@Id
private long id;
@OneToMany (mappedBy = "e")
@Cascade ({ CascadeType.ALL })
private Set<C> cs;
}
下面是我执行的应用程序的步骤:从回购
- 拉
B
;如果存在,则更新其某些字段值[或]用字段值创建新的B
。 - 创建
A
的新实例并将B
设置为A
。 - 坚持
A
(调用JpaCrudRepository.save(A)
)。
成功部分: 一切正常,当B
不存在回购已经。这意味着:
- 创建
B
(和C
,D
,E
)的新实例, - 这个新创建的
B
被设置为A
, - 而
A
仍保持为成功回购(新行插入DB/repo中的所有对应表中)。
故障部位:
- 现在,当
B
在回购已经存在,现有B
适当拉,而C
,D
,E
都保持不变 - 的
B
某些字段被更新, - 而此更新的
B
设置为A
。 - 但是,当试图持续
A
现在在D
和E
上引发唯一约束冲突。
所有实体均标有以下几点:
• ID as auto-generated column (used as PK implicitly),
• Mapping between entities using the ID column,
• CascadeType ALL wherever mappings like OneToMany, ManyToOne are applied,
• Dynamic update annotation.
到目前为止,我可以从网络上收集关于这个问题:
JPA的库没有合并()或update()操作明确可用,并且save()应该覆盖这些操作。这个save()操作通过调用merge()来实现,如果实体实例已经存在的话,或者如果它是新的,则调用persist()。并且进一步挖掘,实体的ID列正被用于确定其在回购中的存在。如果该ID为空,则实体被确定为新的,并且如果ID不为空,则存在实体。
因此,在我上面的失败案例中,由于现有B
实体实例正在从回购中拉出,因此它已具有非空ID。
所以我目前不清楚我在这里错过了什么。 我尝试过在网上找到任何匹配的解决方案,但还是无法到达。
有人能帮我找出我的方法有什么问题吗?
向我们展示'A' - 'E'的代码,仅包括关联(不需要其他属性)。 – manish
感谢您的期待!我在帖子中添加了模型[A到E]。 – Ram
这个问题还不清楚。你说当'B'已经存在时,'C','D'和'E'保持不变,但是你在'D'和'E'上得到一个唯一的约束违反,这只有在尝试插入时才会发生在'D'和'E'上,根据你的要求没有被尝试。这听起来不对。这是一个特定于您的应用程序的调试问题。 – manish