在学习一点关于hibernate的同时,我遇到了下面提到的案例
下的着名的懒惰初始化异常我有一个A类,它引用了另一个B类并且使用了hibernate我试图用它的id加载A类,而在关闭会话之后我试图打印B类的一些属性,认为hibernate可能已经初始化了该对象,但它只是一个代理对象,这是代码快照
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());
这段代码给了我org.hibernate.LazyInitializationException: could not initialize proxy - no Session
,因为我知道它只给了我B代理,当我试图获取B hibernate的属性抛出异常
我对我的代码进行了一些小改动,这里运行良好的是改变版本
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());
}
虽然它有效,但我不确定这是否正确,请建议
答案 0 :(得分:3)
绝对不是正确的方法。
了解你想要的东西:你想要加载A,然后获得与A相关的所有Bs。 理解你做了什么:你加载了A,然后将B设置为'b',这可能会也可能不会改变B的值。
您可以通过多种方式正确完成此操作。
1)在您的应用中使用视图过滤器中的开放会话。有些人认为它是反模式,但很多开发人员都这样做,我个人认为没问题。
2)创建一个自定义查询,一次性获取您需要的所有内容。您可以编写一些hql,当您获取A时,它将获得与A关联的所有B。
3)在会话激活时调用a.getB()
,hibernate会为你获取它。
4)使关联不是懒惰,但我不会这样做,因为它会很慢。如果你在获得A时总是想要Bs,那么你可以做到,但只有在那种情况下。