JPA双向@OneToOne和级联合并



如果我有这两个实体:

@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中,至少有时),但规范并不能保证这一点。

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

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

合并操作的实际语义可以在3.2.7.1合并JPA规范最终版本的Detached Entity State中找到。根据您放入的对象和当前持久性上下文,它的行为会有所不同。

旁注:只要你不使用扩展的持久化上下文,一个实体在事务结束后就会分离。

还请注意,通常不应该使用==操作符比较对象,因为这实际上不是您希望的对象比较的语义(jvm标识不等于业务对象标识)

最新更新