Hibernate @OneToMany与mappedBy(父子)关系和缓存问题

art*_*emb 8 persistence caching hibernate parent-child one-to-many

我有这个问题已经有很长一段时间了,我已经在网上搜索了SO而且还没有找到解决方案.我希望你能帮助我.

我在两个实体之间有一个父子关系,如下所示:

@Entity
public class Parent {
    // ...

    @OneToMany(mappedBy = "parent", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
    private Set<Child> children = new HashSet<Child>();

    // ...
}

@Entity
public class Child {
    // ...

    @ManyToOne(fetch = FetchType.LAZY)
    private Parent parent;

    // ...
}
Run Code Online (Sandbox Code Playgroud)

问题在于,当我创建一个新子节点并将其分配给父节点时,父节点在缓存中时不会更新.

 Parent parent = new Parent();
 em.persist(parent);

 // ...

 Child child = new Child();
 child.setParent(parent);
 em.persist(child);

 parent.getChildren().size(); // returns 0
Run Code Online (Sandbox Code Playgroud)

当孩子被持久化时,我曾尝试使用@PreUpdate自动将子项添加到父项,但是当我们在2个不同的线程中有2个实体管理器时(比如JBoss),问题仍然存在,直到我们调用 em.refresh(parent)

所以问题是 - 有没有办法顺利消除问题并确保parent.getChildren()始终返回最新的儿童名单?

Mic*_*les 8

大多数ORM会以这种方式运作.

缓存中的对象不会从数据库更新(不需要额外的读取).还要将对象模型和持久性视为分离.即保持您的对象模型与自身一致,并且不依赖持久性机制为您执行此操作.

因此,如果您希望将对象添加到集合中,请在"setParent"代码中执行此操作.

在这种情况下,最佳做法实际上是让关系的一方完成所有工作,让另一方推迟.此外,我建议使用字段访问而不是方法访问​​,这样您就可以更灵活地自定义方法.

向名为addChild的父级添加方法

 public void addChild(Child child) {
    child.setParent0(this);
    getChildren().add(individualNeed);
 }
Run Code Online (Sandbox Code Playgroud)

然后在Child中创建setParent:

public void setParent(Parent parent) {
   parent.addChild(child);
}
Run Code Online (Sandbox Code Playgroud)

Child中的setParent0是child上父级的属性stter.

public void setParent0(Parent parent) {
   this.parent = parent;
}
Run Code Online (Sandbox Code Playgroud)

我还建议"getChildren"方法返回一个不可变的集合,这样开发人员就不会无意中不使用这种方法(我在所有这些方面都学到了很多东西).

还有一点,你应该在上面的代码中使用null检查代码和其他防御部分,为了清楚起见,我把它留下了.