一尘不染

Hibernate @OneToMany,具有mappedBy(父子)关系和缓存问题

hibernate

我很长一段时间以来一直遇到这个问题,我已经在网上和网上搜索了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;

    // ...
}

关键是,当我创建一个新的子代并将其分配给父代时,父代已经在缓存中时不会更新。

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

 // ...

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

 parent.getChildren().size(); // returns 0

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

因此,问题是-是否有办法顺利消除问题并确保parent.getChildren()始终返回最新的孩子名单?


阅读 962

收藏
2020-06-20

共1个答案

一尘不染

大多数ORM都将以这种方式运行。

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

因此,如果要将对象添加到集合中,请在“ setParent”代码中执行此操作。

实际上,在这种情况下,最佳实践是让关系的一方完成所有工作,而让另一方顺其自然。我也建议使用字段访问而不是方法访问​​,那样您可以更灵活地自定义方法。

向父方法添加名为addChild的方法

 public void addChild(Child child) {
    child.setParent0(this);
    getChildren().add(individualNeed);
 }

然后在Child中设置setParent:

public void setParent(Parent parent) {
   parent.addChild(child);
}

Child中的setParent0是child上的parent的属性stter。

public void setParent0(Parent parent) {
   this.parent = parent;
}

我还建议“ getChildren”方法返回一个不可变的集合,以便开发人员不会无意间不使用此方法(我在所有这些方法中都学到了硬道理)。

还有一件事,您应该在上面的代码中包含空检查代码和其他防御性内容,为清楚起见,我将其省略。

2020-06-20