使用 Hibernate,我可以在人员/地址之间进行双向关联。个人实体可能有太多地址,我想添加和删除地址集合而不加载整个集合。
下面是描述我的情况的示例,在我的实际情况中,地址实体的数量很大,我想在添加/删除时避免加载所有这些实体。
Java 类:
public class Person
{
private UUID id;
@OneToMany(mappedBy = "person", fetch = FetchType.LAZY, cascade= {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Address> addresses = new HashSet<>();
public Person addAddress(Address address) {
addresses.add(address);
address.setPerson(this);
return this;
}
public Person removeAddress(Address address) {
// though i want to remove one specific address entity association,
// it loads all addresses which is a lot impacting perf
addresses.remove(address);
address.setPerson(null);
return this;
}
}
public class Address {
@ManyToOne(cascade={CascadeType.PERSIST}, fetch = FetchType.LAZY)
@NotNull
private Person person;
public void setPerson(Person person) {
this.person = person; ...
}
}
当我想取消某个地址与 Person 实体的关联时,我调用 person.removeAddress(address) 来加载此人的所有地址。就我而言,有 100 个,我想避免将它们全部加载到内存中。
对实体完成修改后,我会调用
personRepository.flush()
并且不执行任何手动 HQL 查询。
当我只想删除一个给定的地址关联时,是否有任何解决方案可以避免加载此人的所有地址?
public class Person
{
private UUID id;
@OneToMany(mappedBy = "person", fetch = FetchType.LAZY, cascade= {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Address> addresses = new HashSet<>();
public Person addAddress(Address address) {
if (Hibernate.isInitialized(addresses)) {
addresses.add(address);
}
address.setPerson(this);
return this;
}
public Person removeAddress(Address address) {
if (Hibernate.isInitialized(addresses)) {
addresses.remove(address);
}
address.setPerson(null);
return this;
}
}
在上面的添加/删除方法中,我使用
Hibernate.isInitialized
方法来检查集合是否已加载到休眠缓存中,然后才修改集合,否则,我更新关系的另一端,即地址->人员并且有效.
更新关系的另一方就足够了,不需要更新集合,因为地址是此处关系的所有者方。
通过在 Person 类中包含mappedBy属性,我们将其标记为反面。同时,我们还对Address.person字段进行@ManyToOne注解,使Address成为拥有方。
来自:https://www.baeldung.com/hibernate-one-to-many
基于此,Hibernate知道Address的引用更重要,并将Address的引用保存到数据库中。
注意:如果地址收集已初始化,则应使用正确的引用进行更新。否则,可能会导致诸如映射陈旧引用之类的问题。