【发布时间】:2014-09-17 14:37:55
【问题描述】:
假设我在父子之间有双向的一对多关联,映射如下:
父.java:
@Entity
public class Parent {
@Id
private Integer id;
@OneToMany(mappedBy = "parent")
private List<Child> childs = new ArrayList<>();
...
和 Child.java:
@Entity
public class Child {
@Id
private Integer id;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
...
当我运行这段代码时
Parent parent = new Parent(1);
Child child = new Child(1);
Child child2 = new Child(2);
child.setParent(parent);
child2.setParent(parent);
parent.getChilds().add(child);
parent.getChilds().add(child2);
parentRepository.save(parent);
我得到异常
Unable to find Child with id 1
先救孩子也无济于事,只有例外不同
【问题讨论】:
-
好吧,这里有一些澄清:
-
我需要保存父级而不保存子级,这就是不需要级联的原因。在我的情况下,瞬态不是一个解决方案,我仍然希望孩子们急切地加载父级负载。因此,如果没有级联,Spring JPA(或休眠持久性提供者,不确定哪个负责)正在检查每个孩子的持久性。如果我无论如何都不会保存它们(或稍后会保存),那么检查的意义何在?
-
为什么要在持久化父级之前将子级添加到父级,但又不想持久化它们? - 如何首先持久化父实体,然后使用持久化父实体,根据需要添加子实体?完成后,您将
merge()新父级的状态(包括子级)写入数据库。 -
这一切都是因为我没有与数据库保持一致的同步,假设我的实体可以及时改变,如果我有 1000 个孩子的父母,没有级联我只是检查孩子是否被改变(它有一个额外的布尔属性)并只保存/合并它。如果我使用 cascade 它会通过请求数据库检查每 1000 个孩子(我不是在谈论那里的其他关系),那就是很多数据库请求!
-
我认为这只是部分正确。只要您使用单个持久性上下文并且不从其中分离持久性实体,对象就会“附加”到它。这意味着上下文将能够(通过代理对象或检测)准确地确定自上次与数据库同步以来哪个持久对象的哪个属性发生了变化,并且只保留/合并那些,而无需额外的回合-去数据库。这基本上意味着持久性提供程序已经管理并使用了一个内部标志来让您注意哪些对象是“脏的”w.r.t。数据库。