I have a few entities with lazy one to many relationships (logic omitted for brevity):
@Entity
class A{
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "a_pk", nullable = false)
List<B> blist = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "a_pk", nullable = false)
List<C> clist = new ArrayList<>();
@Column(name = "natural_identifier", nullable = false)
private String id;
}
@Entity
class B{
}
@Entity
class C{
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "c_pk", nullable = false)
List<D> dlist = new ArrayList<>();
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "c_pk", nullable = false)
List<E> elist = new ArrayList<>();
}
@Entity
class D{
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
@JoinColumn(name = "d_pk", nullable = false)
List<F> flist = new ArrayList<>();
}
@Entity
class E{
}
@Entity
class F{
}
In some (very rare) case I want to load an instance of A and all of its associations eagerly. The reason for that is that I want to make some modifications on that A instance and it's children as a whole, and then either save or discard them, depending on user input.
If I were to load things as they are needed, I'd have to reattach entities to a new session on user request, but they are being modified, and modifications should not be persisted yet.
So I write something like that:
Session session = sessionFactory.openSession();
s.beginTransaction();
Criteria c = session
.createCriteria(A.class)
.add(Restrictions.eq("id", someValue))
.setFetchMode("blist", SELECT)
.setFetchMode("clist", SELECT)
.createAlias("clist", "c")
.setFetchMode("c.dlist", SELECT)
.setFetchMode("c.elist", SELECT)
.createAlias("c.dlist", "d")
.setFetchMode("d.flist", SELECT);
A a = (A) c.uniqueResult();
session.close(); // line 150
a.getBlist().size(); // line 152 - debug
a.getClist().size(); // line 153 - debug
When I try to access stuff I get an exception on line 152
:
org.hibernate.LazyInitializationException:
failed to lazily initialize a collection of role:
A.blist, could not initialize proxy - no Session
If I change fetch strategy to JOIN
everywhere in the criteria, I get the same exception, but on line 153
(in other words, the first association gets loaded, but not the others).
EDIT: Alexey Malev suggested that fetch mode is set for an alias; it does seem to be true. With a following criteria:
Criteria c = session
.createCriteria(A.class)
.add(Restrictions.eq("id", someValue))
.setFetchMode("blist", JOIN)
.setFetchMode("clist", JOIN);
I'm getting a different Exception: org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags
on line 149. So, join-fetching is not an option.
The question is, how do I load the whole thing?
Hibernate version 4.2.12.Final