Hi everyone, I`ve encountered pretty weird situation with lazy initialized collections. Here is an example of entity:
Code:
@Entity
@Table(name = "MyEntity")
public class MyEntity implements Serializable {
@Id
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "uuid2")
private String uuid;
private String guid;
private Boolean isLast;
private String name;
@ManyToOne
private MyEntity previous;
@ManyToOne
@JoinColumnsOrFormulas({
@JoinColumnOrFormula(column = @JoinColumn(name = "parent_guid", referencedColumnName = "guid")),
@JoinColumnOrFormula(formula = @JoinFormula(referencedColumnName = "isLast", value = "1"))
})
private MyEntity parent;
@OneToMany
@JoinColumn(name = "parent_guid", referencedColumnName = "guid")
@Where(clause = "isLast = 1")
private Set<MyEntity> children;
... getters/setters etc ...
}
And some code:
Code:
Session sess = null;
Transaction tran;
SessionFactory sf = new Configuration().configure("/hibernate.cfg.xml").buildSessionFactory();
try {
sess = sf.openSession();
System.out.println("Session: " + sess);
tran = sess.beginTransaction();
MyEntity parent = new MyEntity();
parent.setGuid(UUID.randomUUID().toString());
parent.setLast(true);
parent.setName("Parent");
sess.saveOrUpdate(parent);
String childGuid = UUID.randomUUID().toString();
MyEntity child1 = new MyEntity();
child1.setGuid(childGuid);
child1.setName("Child");
child1.setLast(false);
child1.setParent(parent);
sess.saveOrUpdate(child1);
MyEntity child2 = new MyEntity();
child2.setGuid(childGuid);
child2.setName("Child*");
child2.setLast(true);
child2.setParent(parent);
child2.setPrevious(child1);
sess.saveOrUpdate(child2);
tran.commit();
sess.close();
sess = sf.openSession();
MyEntity persistentParent = (MyEntity) sess.get(MyEntity.class, parent.getUuid());
System.out.println("Parent`s children count " + persistentParent.getChildren().size());
for (MyEntity persistentChild : persistentParent.getChildren()) {
System.out.println("Child`s children count " + persistentChild.getChildren().size());
}
sess.close();
} catch (Throwable ex) {
ex.printStackTrace();
} finally {
if (sess != null && sess.isOpen()) {
sess.close();
}
}
That produces following output:
Code:
Parent`s children count 1
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: test.MyEntity.children, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572)
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212)
at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:153)
at org.hibernate.collection.internal.PersistentSet.size(PersistentSet.java:160)
at test.Main.main(Main.java:49)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
In my real application I was able to resolve this issue by changing Hibernate version from 4.3.0.Final to 4.1.9.Final, but in this example exception remains in both versions.
Is this a bug or I am missing something?
P.S. I`ve posted example sources at google-docs: https://drive.google.com/file/d/0B2JjyV4_2o5RLXJkb0dKRUtmU00/edit?usp=sharing