如何手动打开hibernate会话?

时间:2009-05-19 18:53:34

标签: java hibernate spring lazy-loading

我有一个涉及spring和hibernate的相当大的项目。现在,我正在将某些对象从休眠状态和内存中支持出来,而且我遇到了一些障碍。我有以下设置。

A类包含许多基元和B类.B包含基元和C类,以前是延迟加载

现在我有了这个

服务电话1:
   1.)创建A类对象    2.)得到B类的对象    3.)在A中设置B.    4.)将A添加到内存

服务电话2:
   1.)从记忆中得到A    2.)从A
获得B.    3.)从B中获得C.    4.)在C

上运作

因为C是延迟加载的,所以它依赖于现有的hibernate会话从懒惰地从B加载自身,至少我相信这是如此。但是,现在,我需要延迟加载而不修改DAO以返回ID,并且存在无当前 hibernate会话以劫持OpenSessionInView。考虑到局限性,解决这个问题的最佳方法是什么?我发现的唯一解决方案依赖于不合适的代码更改或现有会话,因此我认为我可以手动打开一个hibernate会话。我该怎么做呢?或者,这个问题有更好的解决方案吗?

5 个答案:

答案 0 :(得分:5)

作为最佳做法,您需要使用会话工厂。这是Netbeans生成的一个。

public class HibernateUtil {

    private static final SessionFactory sessionFactory;
    private static final Configuration configuration = new Configuration().configure();

    static {
        try {
            // Create the SessionFactory from standard (hibernate.cfg.xml) 
            // config file.
            sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
        } catch (Throwable ex) {
            // Log the exception. 
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

完成此操作后,您可以将此代码用于交易

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();
//Do something
session.getTransaction().commit();

请注意,打开一个交易会打开一个会话。我相信在纯Hibernate下(与JPA不同),你需要一个事务来做任何事情,甚至是读取。

在程序结束时,您要确保执行此操作

HibernateUtil.getSessionFactory().close();

对于更复杂的解决方案,您可能希望查看使用Spring或EJB的自动会话/事务管理。一旦配置正确,将在后台处理会话。

修改
只需重新阅读您的问题和您对ID的观点。我相信sessionfactory方法将适用于您的目的,除非您正在进行多线程应用程序。这是因为,默认情况下,Hibernate会话和链接到该会话的ORM对象仅与一个线程相关联。如果我错了,请告诉我。

答案 1 :(得分:2)

如果您可以获得对已配置的SessionFactory的引用,您应该只能在其上调用openSession()。

答案 2 :(得分:1)

您使用HibernateTemplateHibernateDaoSupport来实施DAO吗?如果是这样,这就是您的对象断开连接的原因。但是,在这种情况下,您应该可以使用OpenSessionInViewInterceptor。你有没有做过任何事情来验证你将无法使用拦截器?

此外,如果您选择打开新的Session,内存中的对象将不会与新的Session相关联。您需要将对象重新连接到会话,以便延迟加载工作。

答案 3 :(得分:1)

如果您知道您的B对象可能引用了它们的C,那么您应该以预取C的方式检索B。例如HQL

from B as b where b.id = :ID

变为

from B as b left join fetch b.c where b.id = :ID

答案 4 :(得分:-3)

简单地使用 Session session = new Configuration()。configure()。buildSessionFactory()。getCurrentSession(); 要么 Session session = new Configuration()。configure()。buildSessionFactory()。getOpenSession();