如何在不加载父集Set集的情况下持久化一个Hibernate子实体 [英] How to persist a Hibernate child entity without loading the parent-side Set collection
问题描述
情况
我有一个父
和一个小孩
实体之间的双向一对多关系, 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屋!