【问题标题】:Should session and factory be closed?会话和工厂是否应该关闭?
【发布时间】:2016-01-19 02:21:24
【问题描述】:

我正在使用带有数据源连接的 Hibernate 5.0.2.Final(在 Tomcat 8.0.15 上)并开始问自己是否不仅需要关闭 Session,还需要关闭 SessionFactory?

现在看起来像这样:

public static List<HibernateList> getHibernateList() {
        Session session = null;
        final String hql = "SELECT H FROM myhibernate.MyHibernate";
        try {
            SessionFactory factory = HibernateUtil.getSessionFactory();
            session = factory.openSession();
            session.beginTransaction();

            Query query = session.createQuery(hql);

            return query.list();
        } catch (HibernateException hibex) {
            Logger.getLogger(Hibernatepicker.class.getName()).log(Level.INFO, null, hql);
            Logger.getLogger(Hibernatepicker.class.getName()).log(Level.SEVERE, null, hibex);
        } finally {
            try {
                if (session != null) {
                    session.close();
                }
            } catch (HibernateException hibex) {
            }//Nothing I could do...
        }
        return null;
    }

来自 hibernate.cfg.xml 的一些细节

<property name="hibernate.connection.datasource">java:comp/env/jdbc/sqlserv</property>        
<property name="current_session_context_class">thread</property> 
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property> 
<property name="hbm2ddl.auto">auto</property> 
<property name="show_sql">false</property>       
<property name="hibernate.generate_statistics">true</property>  

还有 HibernateUtil:

public class HibernateUtil {
private static final SessionFactory sessionFactory;

static {
    try {
        Configuration cfg = new Configuration();
        sessionFactory = cfg.configure("hibernate.cfg.xml").buildSessionFactory();
    } catch (Throwable ex) {
        Logger.getLogger(HibernateUtil.class.getName()).log(Level.SEVERE, null, ex);
        throw new ExceptionInInitializerError(ex);
    }
}

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

我不确定是否有必要在 finally-block 中调用此方法而不是仅关闭会话:

public static void disconnect(Session session, SessionFactory factory) {
        try {
            if (session != null) {
                session.close();
            } else {
                Logger.getLogger(HibernateUtil.class.getName()).log(Level.INFO, null, "Session is Null");
        }

    } catch (HibernateException | NullPointerException hibex) {
        Logger.getLogger(HibernateUtil.class.getName()).log(Level.INFO, null, "Couldn't close session, but there's nothing we can do...");
        Logger.getLogger(HibernateUtil.class.getName()).log(Level.SEVERE, null, hibex);
    }
    try {
        if (factory != null) {
            factory.close();
        } else {
            Logger.getLogger(HibernateUtil.class.getName()).log(Level.INFO, null, "Factory is Null");
        }

    } catch (HibernateException | NullPointerException hibex) {
        Logger.getLogger(HibernateUtil.class.getName()).log(Level.INFO, null, "Couldn't close session, but there's nothing we can do...");
        Logger.getLogger(HibernateUtil.class.getName()).log(Level.SEVERE, null, hibex);
    }
}

【问题讨论】:

    标签: java hibernate hibernate-5.x


    【解决方案1】:

    您不应该在每次查询时关闭您的SessionFactory。您的SessionFactory 每个应用程序只应初始化一次。

    来自hibernate documentation

    这里的主要合约是创建 Session 实例。通常 一个应用程序有一个 SessionFactory 实例和线程 服务客户端请求从该工厂获取 Session 实例。 SessionFactory 的内部状态是不可变的。一旦是 创建了这个内部状态设置。这种内部状态包括所有 关于对象/关系映射的元数据。

    实现者必须是线程安全的。

    【讨论】:

    • 太好了,感谢您的快速回复。有什么方法可以确保它只初始化一次?
    • @Qohelet 是的。您可以使用单例模式来确保单一初始化,或者如果您使用任何 CDI 环境(如 Spring 等),它们都支持内置的这种功能。
    • 我的 HibernateUtil 看起来有点像 Singelton...?我的假设是正确的吗?
    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    相关资源
    最近更新 更多