休眠@OneToMany 与mappedBy(父子)关系和缓存问题 [英] Hibernate @OneToMany with mappedBy (parent-child) relationship and cache problem

查看:33
本文介绍了休眠@OneToMany 与mappedBy(父子)关系和缓存问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个问题很久了,我已经在网上和SO进进出出搜索,但还没有找到解决方案.我希望你能帮助我.

I have this problem for a long time now, I have searched the web and SO in and out and didn't find a solution yet. I hope you can help me on that.

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

I have a parent-child relationship between two entities like the following:

@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;

    // ...
}

问题是,当我创建一个新子项并将其分配给父项时,父项已经在缓存中时不会更新.

The thing is that when I create a new child and assign it to a parent, the parent doesn't get updated when it is in the cache already.

 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)

I have tried to use @PreUpdate to automatically add the child to the parent when the child is persisted, but in the case when we have 2 entity managers in 2 different threads (like in JBoss), the issue still exists, until we call em.refresh(parent)

那么问题是 - 有没有办法顺利消除问题并确保 parent.getChildren() 总是返回最新的孩子列表?

So the question is - is there a way to smoothly eliminate the problem and ensure that parent.getChildren() always return the up-to-date list of children?

推荐答案

大多数 ORM 都会这样做.

Most ORM's will behave this way.

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

The object in the cache is not updated from the database (an extra read that is not necessary). Also think of the object model and the persistence as separate. i.e. keep your object model consistent with itself and don't rely on the persistence mechanism to do this for you.

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

So if you want the object to be added to the collection then do that in the "setParent" code.

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

The best practice in this case is in fact to make one side of the relationship do all the work and let the other side defer onto it. Also I would suggest using field access rather than method access, that way you can customise methods with greater flexibility.

向父级添加一个名为 addChild 的方法

Add a method to parent called addChild

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

然后在 Child 中设置 setParent:

and then make setParent in Child:

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

Child 中的 setParent0 是 parent 对 child 的属性.

setParent0 in Child is the property stter for parent on child.

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

我还建议getChildren"方法返回一个不可变的集合,这样开发人员就不会无意中不使用这个方法(我在这一切中学到了艰难的方法).

I would also suggest that the "getChildren" method return an immutable collection so that developers don't inadvertantly not use this method (I learnt the hard way in all of this).

还有一点,你应该在上面的代码中有空检查代码和其他防御性的部分,为了清楚起见,我把它省略了.

One more thing, you should have null checking code and other defensive pieces in the above code, I left it out for clarity.

这篇关于休眠@OneToMany 与mappedBy(父子)关系和缓存问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆