java - JPA双向@OneToOne与级联合并

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

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

最佳答案

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

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

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

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

关于java - JPA双向@OneToOne与级联合并,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15438040/

相关文章:

java - 使用 JPA 连接不区分大小写的 PK 和 FK 表

java - 填充相交的两条线之间的区域?

java - 如何杀死从java派生的jni进程

javax.validation.ValidationException : HV000041: Call to TraversableResolver. isReachable() 抛出异常

mysql - JPA:如何表示JoinTable和JoinTable的组合键?

java - hibernate 复合键: foreign key has wrong number of columns

java - 部署多模块Play项目

java - 如何使用maven构建spring boot应用程序的库jar

java - scala play 框架中的自定义消息属性,用于删除硬编码字符串

java - 相互客户端身份验证在 Servlet 中获取证书