Hibernate Lazy初始化问题

时间:2011-08-03 18:00:10

标签: hibernate

在学习一点关于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());
}

虽然它有效,但我不确定这是否正确,请建议

1 个答案:

答案 0 :(得分:3)

绝对不是正确的方法。

了解你想要的东西:你想要加载A,然后获得与A相关的所有Bs。 理解你做了什么:你加载了A,然后将B设置为'b',这可能会也可能不会改变B的值。

您可以通过多种方式正确完成此操作。

1)在您的应用中使用视图过滤器中的开放会话。有些人认为它是反模式,但很多开发人员都这样做,我个人认为没问题。

2)创建一个自定义查询,一次性获取您需要的所有内容。您可以编写一些hql,当您获取A时,它将获得与A关联的所有B。

3)在会话激活时调用a.getB(),hibernate会为你获取它。

4)使关联不是懒惰,但我不会这样做,因为它会很慢。如果你在获得A时总是想要Bs,那么你可以做到,但只有在那种情况下。