问题
Let's say 2 entities are given: master and dependant.
They are defined in DB usually like dependants.master_id -> masters.id
, i.e. the dependant entity holds the reference to the main entity.
In JPA one2one BiDirectional association in this case usually looks like:
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.
回答1:
One workaround might be using @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.
回答2:
You have multiple options, but all depend on setting the relationship correctly on the owning side, which in your case is 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.
Given that you are using field-level access, you could also consider making Master.setDependant()
do the work for you:
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. You will then want to ensure that persistence operations are specified to cascade correctly from Master
to Dependant
.
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
. It will likely also fail if you try to replace a Master
's Dependant
without explicitly removing the original one, if any. 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.
来源:https://stackoverflow.com/questions/54988105/how-to-properly-manage-associated-jpa-entities-with-onetoone-bidirectional-relat