我们使用的是带有Hazelcast 3.6.1 2级缓存的Hibernate 3.5.6-Final。
我Parent和Child具有Hibernate设置的实体之间存在双向,一对多关系inverse = true。实体类定义如下:
Parent
Child
inverse = true
class Parent { Set<Child> children; ... // setters, getters, other properties } class Child { Parent parent; ... // setters, getters, other properties }
父级的Hibernate映射定义如下:
<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>
子项的hibernate映射定义如下:
<many-to-one name="parent" class="Parent" cascade="none" column="parent_id" not-null="true"/>
现在,当前代码Child向中添加了,Parent如下所示:
child.setParent(parent); parent.getChildren().add(child);
问题是第二行代码导致Hibernate加载 所有 子代。在我们的设置中,这是一个非常昂贵的操作,因为子实体具有渴望的集合,而这些实体又具有具有渴望的集合的实体。
当前不能更改Hibernate模型。
我将上面的代码更改如下:
child.setParent(parent); sessionFactory.getCache().evictCollection( "Parent.children", parent.getId() );
到目前为止,这一直有效。现在的明显问题是,如果在执行代码之前加载children了当前会话中的父级集合,则该集合 可能 已过时。我想确保在随后进行的任何调用都parent.getChildren()返回最新的集合,而无需真正地将子项显式添加到集合中。我实际上想告诉Hibernate使集合无效,以便在需要时再次加载集合。
children
parent.getChildren()
我找到了解决问题的方法。我通过在上添加了一个新方法addChild来解决它,Parent如下所示:
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将加载包括新子集的集。