3

如果我有这两个实体:

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

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

4

1 回答 1

1

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

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

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

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

于 2013-03-15T20:47:53.007 回答