Reputation: 23587
while learning a bit about hibernate i came across famous lazy initialization exception under below mentioned case
i have a class A which has reference to another class B and using hibernate i was trying to load class A using its id and than after closing the session i was trying to print some properties of class B thinking that hibernate might have initialized the object but all it did was a proxy object, here is the code snap
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
a=(A)session.load(A.class, "40288184318d9a3c01318d9a3eea0001");
tx.commit();
} catch (Exception e) {
log.error("Unable to complete the transcation"
+ "Transcation will be roll backed", e);
e.printStackTrace();
tx.rollback();
} finally {
log.info("Closing the session");
if (session != null && session.isOpen() == true){
session.close();
}
}
System.out.println(a.getUuid());
System.out.println(a.getB().getShortDescription());
System.out.println(a.getB().getLongDescription());
System.out.println(a.getB().getName());
this code was giving me org.hibernate.LazyInitializationException: could not initialize proxy - no Session
since i know it has given me only proxy for B and when i tried to get properties of B hibernate throws exception
i did a small change in my code and it worked well here is the changed version
Session session=HibernateUtil.getSessionFactory().openSession();
Transaction tx = session.getTransaction();
try {
tx.begin();
a=(A)session.load(A.class, "40288184318d9a3c01318d9a3eea0001");
tx.commit();
} catch (Exception e) {
e.printStackTrace();
tx.rollback();
} finally {
//log.info("Closing the session");
if (session != null && session.isOpen() == true){
b=des.getB();
session.close();
}
}
a.setB(b);
System.out.println(a.getUuid());
System.out.println(a.getB().getShortDescription());
System.out.println(a.getB().getLongDescription());
System.out.println(a.getB().getName());
}
though it is working but i am not sure if this is correct approach or not, please suggest
Upvotes: 0
Views: 2978
Reputation: 120188
Definitely NOT the right approach.
Understand what you want: you want to load A, and then get all Bs associated with A. Understand what you did: you loaded A, then set B to 'b', which might or might not have changed the value of B.
You have a number of options to do it correctly.
1) Use an open session in view filter in your app. Some people consider it an anti-pattern, but a lot of developers do it, and I personally think its ok.
2) Create a custom query which gets you everything you need in one go. You can write some hql that will get all Bs associated to an A when you fetch an A.
3) Call a.getB()
while the session is active, and hibernate will fetch it for you.
4) Make the association not lazy, but I would not do that as it will be slow. If you always want Bs when you get A, then you can do it, but only in that case.
Upvotes: 3