如何正确管理具有 OneToOne BiDirectional 关系的关联 JPA 实体?

How to properly manage associated JPA entities with OneToOne BiDirectional relation?

假设给定了 2 个实体:master 和 dependant。

它们在数据库中的定义通常类似于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);

是否有任何常见的解决方法?我的意思是我不想搞乱从依赖方支持协会。

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

硕士

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

依赖

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

或者可能只是省略空值检查。

您有多种选择,但都取决于在拥有方正确设置关系,在您的情况下是 Dependant。最适合您的选择取决于您的需求和使用模式。例如,另一个答案讨论了定义 @PrePersist 方法,如果 MasterDependent 之间的关联是在且仅当 masters 首次持久化时建立的,则该方法可能非常干净。

鉴于您使用的是字段级访问权限,您还可以考虑让 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 侧建立互惠关系。然后,您需要确保持久性操作被指定为从 Master 正确级联到 Dependant

但是请注意,这不是灵丹妙药。如果您将分离或删除的 Dependant 分配给 Master,它很容易但令人惊讶地失败。如果您尝试替换 MasterDependant 而没有明确删除原始的(如果有的话),它也可能会失败。还有其他方法可以破解它。

由于以非常简单的方式管理关系需要细心和注意细节,我建议您硬着头皮手动操作,无论何时何地,如果您确实需要创建关系之外的任何东西你坚持一个新的 Master 并遍历现有的关系。