简体   繁体   English

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

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

Let's say 2 entities are given: master and dependant. 假设有两个实体:主实体和从属实体。

They are defined in DB usually like dependants.master_id -> masters.id , ie the dependant entity holds the reference to the main entity. 它们通常在DB中定义,就像dependants.master_id -> masters.id ,即,从属实体持有对主实体的引用。

In JPA one2one BiDirectional association in this case usually looks like: 在这种情况下,在JPA one2one双向关联中通常如下所示:

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

And this approach causes the necessity to deal with both sides of relation like: 这种方法导致必须处理关系的双方,例如:

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

instead of more intuitive and closer to business logic one like: 而不是像这样更直观,更接近业务逻辑:

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

Are there any common workarounds for this? 有什么通用的解决方法吗? I mean I don't want to mess with supporting the association from the dependant side. 我的意思是我不想从依赖方支持协会。

One workaround might be using @PrePersist . 一种解决方法是使用@PrePersist For both entities you could implement methods like: 对于这两个实体,您可以实现以下方法:

Master

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

Dependant 依赖的

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

Or maybe just omitting the null checks. 或者也许只是省略空检查。

You have multiple options, but all depend on setting the relationship correctly on the owning side, which in your case is Dependant . 您有多个选项,但是所有选项都取决于在拥有方正确设置关系,在您的情况下,这是Dependant The best choice for you depends on your needs and usage pattern. 最佳选择取决于您的需求和使用方式。 For example, another answer discusses defining a @PrePersist method, which can be pretty clean if the association between Master and Dependent is established when and only when masters are first persisted. 例如,另一个答案讨论了定义@PrePersist方法,如果仅当首次保留master时才建立MasterDependent之间的关联,则该方法非常干净。

Given that you are using field-level access, you could also consider making Master.setDependant() do the work for you: 鉴于您正在使用字段级访问,您还可以考虑让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;
    }

    // ...
}

That will ensure that when you assign a Dependant to a Master , the reciprocal relationship is automatically set up on the Dependant side. 这将确保当你将一个Dependant于一个Master ,倒数关系是自动建立的Dependant方。 You will then want to ensure that persistence operations are specified to cascade correctly from Master to Dependant . 然后,您将要确保已指定持久性操作,以正确地从MasterDependant进行级联。

Note, however, that this is no silver bullet. 但是请注意,这不是灵丹妙药。 It can easily yet surprisingly fail if you assign a detached or removed Dependant to a Master . 如果将分离的或移除的Dependant分配给Master ,则可能很容易却意外地失败。 It will likely also fail if you try to replace a Master 's Dependant without explicitly removing the original one, if any. 如果您尝试替换MasterDependant而没有显式删除原始的Dependant ,则它也可能会失败。 There are other ways to break it, too. 还有其他破解方法。

Inasmuch as managing the relationship in all but very simple ways requires care and attention to detail, I'd suggest that you bite the bullet and do it manually, everywhere, if indeed you need anything more than creating the relationship when you persist a new Master and traversing existing relationships. 由于仅通过非常简单的方式来管理关系需要细心和对细节的关注,我建议您硬着头皮在任何地方手动进行,如果确实需要更多的东西,而不仅仅是在坚持新Master时建立关系并遍历现有关系。

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

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