如何在不加载父集Set集的情况下持久化一个Hibernate子实体 [英] How to persist a Hibernate child entity without loading the parent-side Set collection

查看:77
本文介绍了如何在不加载父集Set集的情况下持久化一个Hibernate子实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们使用Hibernate 3.5.6-Final和Hazelcast 3.6.1二级缓存。

情况



我有一个和一个小孩实体之间的双向一对多关系, Hibernate设置 inverse = true 。实体类定义如下:

  class父类{
Set< Child>儿童;
... // setters,getters,other properties
}

class Child {
父亲;
... // setters,getters,other properties
}

父级的Hibernate映射定义如下:

 < set name =children
lazy =true
inverse =true
cascade =all
sort =unsorted>
< cache usage =read-write/>
< key column =parent_id/>
<一对多班=小孩/>
< / set>

孩子的Hibernate映射定义如下:

 <多对一名称=父母
class =Parent
cascade =none
column = parent_id
not-null =true/>

当前的代码现在将一个 Child 添加到如下:

  child.setParent(parent); 
parent.getChildren()。add(child);

问题在于第二行代码会导致Hibernate加载所有 儿童。在我们的设置中,这是一个非常昂贵的操作,因为子实体具有渴望集合,而实体又有渴望集合。



更改Hibernate模型目前不是一种选择。 / b>

问题



我改变了上面的代码,如下所示:

  child.setParent(父); 
sessionFactory.getCache()。evictCollection(Parent.children,parent.getId());

到目前为止,现在明显的问题是,如果在执行代码之前加载,则当前会话中父代的 children 集合可能过期。我想确保之后对 parent.getChildren()的任何调用都返回最新的集合,而不实际将子集明确地添加到集合中。我实际上想告诉Hibernate使集合无效,以便它在需要时再次加载集合。 我找到了一个解决方案对我的问题。我通过向添加一个新方法 addChild 来解决它,如下所示:

  public void addChild(Child child){
child.setParent(this);
if(Hibernate.isInitialized(getChildren()){
getChildren()。add(child);
} else {
Hibernate.getSessionFactory()。getCache()。evictCollection (
getClass()。getName()+。children,this.getId());
}
}

因此:如果孩子已经因为某种原因被加载了,新的孩子被添加到孩子集中,这确保已经加载的集合保持一致。是不加载的,我只是将父项设置为子项并驱逐第二级缓存(这是需要的描述: https://github.com/hibernate/hibernate-orm/pull/580 )。由于集合尚未加载,它也不能不一致,当后来访问集合时,Hibernate会加载包含新子集的集合。


We are using Hibernate 3.5.6-Final with Hazelcast 3.6.1 2nd level cache.

Situation

I have a bi-directional, one-to-many relation between a Parent and a Child entity with the Hibernate setting inverse = true. The entity classes are defined as follows:

class Parent {
   Set<Child> children;
   ... // setters, getters, other properties
}

class Child {
   Parent parent;
   ... // setters, getters, other properties       
}

The Hibernate mapping of the parent is defined as follows:

<set name="children"
     lazy="true"
     inverse="true"
     cascade="all"
     sort="unsorted">
     <cache usage="read-write"/>
     <key column="parent_id"/>
     <one-to-many class="Child"/>
</set>

The Hibernate mapping of the child is defined as follows:

<many-to-one name="parent"
    class="Parent"
    cascade="none"
    column="parent_id"
    not-null="true"/>

The current code now adds a Child to the Parent as follows:

child.setParent(parent);
parent.getChildren().add(child);

The problem is that the second line of code causes Hibernate to load all children. In our setting this is a very expensive operation as the child entities have eager collections that have entities with eager collections again.

Changing the Hibernate model is currently not an option.

Question

I changed the above code as follows:

child.setParent(parent);
sessionFactory.getCache().evictCollection( "Parent.children", parent.getId() );

This worked so far. The apparent problem now is that the children collection of the parent in the current session might be outdated if it was loaded before the code was executed. I want to ensure that afterwards any call to parent.getChildren() returns the up-to-date collection, without actually adding the child explictly to the collection. I actually would like to tell Hibernate to invalidate the collection so that it loads the set again if needed.

解决方案

I found a solution to my problem. I solved it by adding a new method addChild to the Parent that looks as follows:

 public void addChild(Child child) {
     child.setParent(this);
     if (Hibernate.isInitialized(getChildren()) {
         getChildren().add(child);
     } else {
         Hibernate.getSessionFactory().getCache().evictCollection(
             getClass().getName()+".children", this.getId());
     }
 }

Thus: if the children have already been loaded for some reason, the new child is added to the children set. This ensures that an already loaded set stays consistent. If the set is not loaded yet, I just set the parent to the child and evict the 2nd level cache (that this is needed is described here: https://github.com/hibernate/hibernate-orm/pull/580). As the set is not loaded yet it can also not be inconsistent. When the set is accessed afterwards, Hibernate will load the set including the new child.

这篇关于如何在不加载父集Set集的情况下持久化一个Hibernate子实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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