Java JPA递归一对一延迟加载引用未更新
使用JPA 2.1和Hibernate 4.3.6.Final,我有以下简单实体:Java JPA递归一对一延迟加载引用未更新,java,hibernate,jpa,Java,Hibernate,Jpa,使用JPA 2.1和Hibernate 4.3.6.Final,我有以下简单实体: @Entity @Table(name = "CONTACT") public class Contact { @Id @Column(name = "ID") private String id = UUID.randomUUID().toString(); @OneToOne(fetch = FetchType.LAZY) @JoinColumn(name = "PA
@Entity
@Table(name = "CONTACT")
public class Contact {
@Id
@Column(name = "ID")
private String id = UUID.randomUUID().toString();
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARTNER_ID")
private Contact partner;
Contact() {
}
public void assignPartner(final Contact other) {
this.partner = Objects.requireNonNull(other);
other.partner = this;
}
public void unassignPartner() {
if (partner != null) {
partner.partner = null;
}
partner = null;
}
}
注意延迟加载的一对一递归关联到合作伙伴联系人。还要注意assignPartner和unassignPartner如何管理双向关系
以及以下方法:
private static void assignPartner(final EntityManager entityManager) {
entityManager.getTransaction().begin();
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
final Contact contact2 = entityManager.find(Contact.class, CONTACT2_ID);
contact1.assignPartner(contact2);
entityManager.getTransaction().commit();
}
private static void unassignPartner(final EntityManager entityManager) {
entityManager.getTransaction().begin();
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
contact1.unassignPartner();
entityManager.getTransaction().commit();
}
假设CONTACT1\u ID和CONTACT2\u ID的现有行,在运行assignPartner然后unassignPartner之后,数据库状态显示CONTACT1具有空的partner\u ID,CONTACT2仍然具有非空的partner\u ID
但是,如果我将Contact.partner fetch类型更改为EAGER,则在运行assignPartner然后是unassignPartner之后,数据库状态显示contact1和contact2都有空的partner\u id
为什么呢?为什么对合作伙伴实体的更改没有刷新到数据库中
编辑1
也不会传播通过直接字段访问对合作伙伴引用所做的更改,例如partner.firstName=DUMPED。
通过方法访问对合作伙伴引用的更改(例如partner.setFirstNameDUMPED)将被传播。
未传播partner.partner=null或partner.setPartnernull
编辑2
正如Rat2000所建议的,将取消分配逻辑移到Contact.unassignPartner方法外部和unassignpartnertitymanager方法内部似乎可以正常工作。因此,这实际上与Hibernate如何处理contact1.partner代理有关,特别是contact1.partner.partner代理
final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
contact1.getPartner().unassignPartner();
contact1.unassignPartner();
试试这个:
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.UPDATE)
@JoinColumn(name = "PARTNER_ID")
private Contact partner;
谢谢你的建议,我试过了,结果都一样。提交事务会自动刷新EntityManager,因此这应该没有什么区别。此外,对contact1的更改会刷新到数据库中,但对contact2的更改不会刷新到数据库中。这就是我不明白的。我想你把我弄糊涂了。。。因此,当您保存到数据库时,联系人1的更改将在数据库中显示,但如果您从数据库中重新显示对象contact 2,该对象应具有对联系人1的引用,则联系人合作伙伴为空?contact.unassignPartner为当前实例取消分配合作伙伴,但也为被引用的实例合作伙伴取消分配合作伙伴。因此,在调用contact1.unassignPartner并提交事务后,我希望内存和数据库中都有contact1.partner=null和contact2.partner=null。我在内存中观察到contact1.partner=null和contact2.partner=null,但在数据库中观察到contact1.partner=null和contact2.partner=contact1。恐怕结果是一样的。问题不是contact2没有与EntityManager分离,而是它没有更新……让我们来看看。