We are using Hibernate 3.5.6-Final with Hazelcast 3.6.1 2nd level cache.
I have a bi-directional, one-to-many relation between a Parent
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.
There's a better way:
You need to make the many-to-one side lazy.
<many-to-one name="parent"
class="Parent"
cascade="none"
column="parent_id"
not-null="true"
lazy="true"/>
As long as you don't need to fetch the Parent entity in the currently running Persistence Context, you can just fetch a Proxy reference:
Parent parentProxy = session.load(Parent.class, parentId);
Now, you can simply create a new child as follows:
Child newChild = new Child();
child.setParent(parentProxy);
session.persist(newChild);
Another workaround is as follows:
You don't even fetch a Parent Proxy reference, but instead, you do as follows:
Parent parentReference = new Parent();
parentReference.setId(parentId);
Child newChild = new Child();
child.setParent(parentReference);
session.persist(newChild);
This way, you don't need to fully fetch the Parent entity if all you need is to persist a Child entity.