繁体   English   中英

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

[英]JPA recursive one-to-one lazy-loaded reference not updated

使用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的合作伙伴ID为空,contact2的合作伙伴ID为非空。

但是,如果我将Contact.partner的访存类型更改为EAGER,则在运行assignPartner()之后再取消unassignPartner()之后,数据库状态将显示contact1和contact2的伙伴名称都为空。

这是为什么? 为什么对伙伴实体的更改未刷新到数据库?

编辑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();

尝试这个:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM