【发布时间】:2017-10-04 22:53:27
【问题描述】:
我正在开发一个包含 Spring 数据、JPA、Hibernate 组合的 Spring Boot 应用程序。下面是我正在努力解决的场景,其中预期的行为是仅更新一些子实体,而父实体被插入为新实体。
实体类
@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 在 repo 中不存在时,一切正常。这意味着:
- 创建了
B(和C、D、E)的新实例, - 这个新创建的
B被设置成A, - 并且
A已成功持久化到 repo(在 DB/repo 的所有对应表中插入新行)。
失败部分:
- 现在,当
B已经存在于repo 中时,现有的B会被正确拉取, -
B的某些字段已更新,而C、D、E保持不变, - 并且这个更新的
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 存储库没有明确可用的 merge() 或 update() 操作,而 save() 应该涵盖这些操作。如果实体实例已经存在,则此 save() 操作通过调用 merge() 或者如果它是新的,则通过调用 persist() 来工作。进一步挖掘,实体的 ID 列被用来确定它在 repo 中的存在。如果此 ID 为 null,则实体被确定为新实体,如果 ID 不为 null,则实体被确定为现有。
所以在我上面的失败案例中,由于现有的 B 实体实例正在从 repo 中提取,它已经有一个非空 ID。
所以我目前还不清楚我在这里缺少什么。 我尝试在网上找到任何匹配的解决方案,但还没有找到。
有人可以帮我找出我的方法有什么问题吗?
【问题讨论】:
-
向我们展示
A-E的代码,仅包括关联(不需要其他属性)。 -
感谢收看!我在帖子中添加了模型 [A 到 E]。
-
这个问题还不清楚。你说当
B已经存在时,C、D和E保持不变,但是你在D和E上得到一个唯一的约束违规,这只会在尝试插入时发生在D和E上,根据您的说法,没有尝试过。这听起来不对。这是您的应用程序特有的调试问题。
标签: spring hibernate jpa orm spring-data