JPA双向@OneToOne和级联合并

时间:2013-03-15 16:57:25

标签: java jpa

如果我有这两个实体:

@Entity class A { 
    @OneToOne(cascade = CascadeType.MERGE, mappedBy = "a") B b; 
    //getters+setters
}
@Entity class B { 
    @OneToOne(cascade = CascadeType.MERGE) A a; 
    //getters+setters
}

JPA规范是否保证这个?

A a = new A();
B b = new B();
a.setB(b);
b.setA(a);
A managedA = entityManager.merge(a);
// after commit, managedA will have a reference to a managed B which JPA implementation will link to managedA instead of original unmanaged A
Assert.assertTrue(managedA.getB().getA() == managedA);

我的理解是它起作用(至少有时候是最新的EclipseLink),但规范并不保证。

反例/规格摘录欢迎: - )

1 个答案:

答案 0 :(得分:1)

你是对的,JPA规范并不保证。事实上,在大多数情况下,merge()的语义是它返回一个新实例 - 由实体管理器创建的托管实例,给定对象的状态合并到其中 - 但这只是一个简化。如果它附加了你放入的对象,那么该方法实际上可以返回void(就像persist()方法那样)。我不知道为什么它的设计是这样的 - 拥有这种不同的语义实际上有点麻烦,我们花了一些时间在我们的应用程序代码中封装了所需的行为。

合并操作的实际语义可以在 3.2.7.1合并JPA规范的分离实体状态最终版本中找到。它的行为会有所不同,具体取决于您放入的对象和当前持久性上下文。

旁注:只要您不使用扩展的持久性上下文,只要事务结束,实体就会变为分离。

另请注意,您通常不应使用==运算符比较对象,因为这实际上不是您对对象比较所需的语义(jvm标识不等于业务对象标识)