问题描述
在学习一些关于hibernate的知识时,我遇到了下面提到的例子中的着名的懒惰初始化异常。我有一个类A,它引用了另一个类B并使用了hibernate我正在尝试使用它的id加载类A,并且在关闭会话后我试图打印一些B类属性,认为hibernate可能已经初始化了对象,但它所做的只是一个代理对象,下面是代码快照 p> Session session = HibernateUtil.getSessionFactory()。openSession();
Transaction tx = session.getTransaction();
尝试{
tx.begin();
a =(A)session.load(A.class,40288184318d9a3c01318d9a3eea0001);
tx.commit();
} catch(Exception e){
log.error(无法完成transcation
+Transcation将被回滚,e);
e.printStackTrace();
tx.rollback();
}最后{
log.info(关闭会议);
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());
这段代码给我 org.hibernate.LazyInitializationException:无法初始化代理 - 没有会话
因为我知道它给了我只有代理B,当我试图获得B的属性Hibernate抛出异常
我做了在我的代码中的一个小改动,它在这里运行得很好,是改变后的版本。
Session session = HibernateUtil.getSessionFactory()。openSession );
Transaction tx = session.getTransaction();
尝试{
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());
}
虽然它正在运作,但我不确定这是否正确方法,请提出建议
绝对不是正确的做法。
了解你想要什么:你想加载A,然后获得与A相关的所有B.
了解你做了什么:你加载了A,然后将B设置为'b',这可能会或可能没有改变B。
您有许多选项可以正确执行此操作。
1)在您的应用中使用视图过滤器中的打开会话。有些人认为这是一种反模式,但很多开发人员都这样做,我个人认为它是可以的。
2)创建一个自定义查询,让您获得所有的东西需要一气呵成。 3)调用 a.getB() / code>,而会话处于活动状态,并且hibernate会为你取回它。
4)使关联不是懒惰的,但我不会那么做它会很慢。如果你总是想要B时,你可以做到,但只有在这种情况下。
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
解决方案 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.
这篇关于Hibernate懒惰初始化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!