如何通过OneToOne双向关系正确管理关联的JPA实体?

时间:2019-03-04 17:03:49

标签: java jpa entity-relationship

假设有两个实体:主实体和从属实体。

它们在数据库中的定义通常类似于dependants.master_id -> masters.id,即从属实体持有对主实体的引用。

在JPA one2one双向关联中,这种情况通常如下所示:

class Master {
    @OneToOne(mappedBy="master")
    Dependant dependant
}
class Dependant {
    @OneToOne
    @JoinColumn("master_id")
    Master master
}

这种方法导致必须处理关系的双方,例如:

Master master = new Master();
Dependant dependant = new Dependant();
dependant.setMaster(master);
master.setDependant(dependant);
repository.save(master);

而不是像这样更直观,更接近业务逻辑:

Master master = new Master();
Dependant dependant = new Dependant();
master.setDependant(dependant);
repository.save(master);

有没有通用的解决方法?我的意思是我不想从依赖方那里支持协会。

2 个答案:

答案 0 :(得分:2)

一种解决方法可能是使用@PrePersist。对于这两个实体,您可以实现以下方法:

大师

@PrePersist
private void prePersist() {
    if(null == getDependant().getMaster()) {
        getDependant().setMaster(this);
    }
}

依赖

@PrePersist
private void prePersist() {
    if(null == getMaster().getDependant()) {
        getMaster().setDependant(this);
    }
}

或者只是省略空检查。

答案 1 :(得分:1)

您有多个选择,但是所有选择都取决于在拥有方面正确设置关系,在您的情况下为Dependant。最佳选择取决于您的需求和使用方式。例如,另一个答案讨论了定义@PrePersist方法的问题,如果MasterDependent之间的关联是在仅当首次保留母版时才建立的,则该方法很干净。

鉴于您正在使用字段级访问,您还可以考虑让Master.setDependant()为您完成工作:

class Master {
    // ...

    @OneToOne(mappedBy="master")
    private Dependant dependant;

    public void setDependant(Dependant dep) {
        if (dep != null) {
            dep.setMaster(this);
        } else if (dependant != null) {
            // leaves a dangling dependant ...
            dependant.setMaster(null);
        }
        dependant = dep;
    }

    // ...
}

这将确保在将Dependant分配给Master时,在Dependant端会自动建立对等关系。然后,您将要确保将持久性操作指定为从MasterDependant正确地级联。

但是请注意,这不是灵丹妙药。如果将分离的Dependant分配给Master,则可能很容易却意外地失败。如果您尝试替换Master的{​​{1}}而没有显式删除原始的Dependant,它也可能会失败。还有其他破解方法。

由于以非常简单的方式来管理关系需要细心和注重细节,因此我建议您硬着头皮,在任何地方手动进行,如果确实需要更多的东西而不是在坚持时创建关系新的Master并遍历现有关系。