Problem
I have the object A, which contains a list of B and B contains a list of C.
I need to load everything from a certain A.
Using Join Fetch is a no-no because of the duplicates.
Also see here: The best way to fix the Hibernate MultipleBagFetchException
Also from the same link, you will notice that making everything a Set so you can join fetch is also bad for performance.
Current Inneficient solution
The current solution proposes that you load A using an ID and initialize the B list using Hibernate.initialize and for each B loaded, apply Hibernate.initialize to load C list.
Its inneficient per nature. However, I dont know how to load everything up using a single query.
@Override
public A find(Long id, Session session, boolean closeSession) {
try {
CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<A> queryA = criteriaBuilder.createQuery(A.class);
Root<A> root = queryA.from(A.class);
queryA.select(root);
queryA.where(criteriaBuilder.equal(root.get("id"), id));
Query<A> query = session.createQuery(queryA);
A singleResult = query.getSingleResult();
//Initialize The Bs List
Hibernate.initialize(singleResult.getBs());
//Initialize each Cs List from each B
for(B b : singleResult.getBs()){
Hibernate.initialize(b.getCs());
}
return singleResult;
} catch (Exception ex) {
throw ex;
} finally {
if (session != null && closeSession) {
session.close();
}
}
}
Question
How to load everything from A(id) with performance ?
@Entity
public class A {
@Id
@GeneratedValue
private Long id;
private String Name;
@OneToMany(fetch = FetchType.LAZY)
private Set<B> bs;
}
@Entity
public class B {
@Id
@GeneratedValue
private Long id;
private String Name;
@OneToMany(fetch = FetchType.LAZY)
private Set<C> cs;
}
@Entity
public class C {
@Id
@GeneratedValue
private Long id;
private String Name;
}