我们正在使用Hibernate 3.5.6-Final和Hazelcast 3.6.1二级缓存。
我在Hibernate设置为Parent
的{{1}}和Child
实体之间存在双向一对多关系。实体类定义如下:
inverse = true
父级的Hibernate映射定义如下:
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>
现在的代码现在向<many-to-one name="parent"
class="Parent"
cascade="none"
column="parent_id"
not-null="true"/>
添加Child
,如下所示:
Parent
问题是第二行代码会导致Hibernate加载所有子项。在我们的设置中,这是一个非常昂贵的操作,因为子实体具有渴望的集合,这些集合具有再次拥有热切集合的实体。
目前无法更改Hibernate模型。
我更改了上面的代码如下:
child.setParent(parent);
parent.getChildren().add(child);
到目前为止一直有效。现在明显的问题是,如果在执行代码之前加载了当前会话中父级的child.setParent(parent);
sessionFactory.getCache().evictCollection( "Parent.children", parent.getId() );
集合可能过时。我希望确保之后对children
的任何调用都会返回最新的集合,而不会将该子项明确地添加到集合中。我实际上想告诉Hibernate使集合无效,以便在需要时再次加载集合。
答案 0 :(得分:0)
有更好的方法:
你需要让多对一的一方懒惰。
<many-to-one name="parent"
class="Parent"
cascade="none"
column="parent_id"
not-null="true"
lazy="true"/>
只要您不需要在当前运行的持久性上下文中获取Parent实体,您就可以获取代理参考:
Parent parentProxy = session.load(Parent.class, parentId);
现在,您可以按如下方式创建一个新子项:
Child newChild = new Child();
child.setParent(parentProxy);
session.persist(newChild);
另一种解决方法如下:
您甚至无法获取父代理参考,而是执行以下操作:
Parent parentReference = new Parent();
parentReference.setId(parentId);
Child newChild = new Child();
child.setParent(parentReference);
session.persist(newChild);
这样,如果您只需要持久保存Child实体,则无需完全获取Parent实体。
答案 1 :(得分:0)
我找到了解决问题的方法。我通过向addChild
添加一个新方法Parent
来解决它,如下所示:
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将加载包括新子节点的集合。