JPA递归的一对一延迟加载引用未更新

时间:2014-08-30 21:03:23

标签: 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 = "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_ID和CONTACT2_ID的现有行,在运行assignPartner()然后unassignPartner()之后,数据库状态显示contact1具有null partner_id,而contact2仍然具有非null partner_id。

但是,如果我将Contact.partner提取类型更改为EAGER,则在运行assignPartner()然后unassignPartner()之后,数据库状态显示contact1和contact2都具有null partner_id。

为什么?为什么伙伴实体的更改没有刷新到数据库?

编辑1

通过直接字段访问更改合作伙伴引用,例如partner.firstName =“DUMPED”,也不会传播。 通过方法访问权限更改合作伙伴参考,例如partner.setFirstName(“DUMPED”)被传播。 无法传播partner.partner = null或partner.setPartner(null)。

编辑2

正如Rat2000所建议的那样,将取消分配逻辑移到Contact.unassignPartner()方法之外和unassignPartner(EntityManager)方法内部似乎正常工作。所以这与Hibernate如何处理contact1.partner代理,特别是contact1.partner.partner代理有关。

    final Contact contact1 = entityManager.find(Contact.class, CONTACT1_ID);
    contact1.getPartner().unassignPartner();
    contact1.unassignPartner();

1 个答案:

答案 0 :(得分:0)

试试这个:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.UPDATE)
@JoinColumn(name = "PARTNER_ID")
private Contact partner;