关闭Hibernate 4.3中的SessionFactory

我正在将我的Hibernate升级到最新版本。 使用我的旧HibernateUtil.java我没有遇到任何问题,但在升级它时,SessionFactory似乎不再关闭了。

这是我新的 HibernateUtil.java类:

 import org.hibernate.HibernateException; import org.hibernate.cfg.Configuration; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { Configuration configuration = new Configuration().configure(); StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()); sessionFactory = configuration.buildSessionFactory(builder.build()); } catch (HibernateException ex) { System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { return sessionFactory; } public static void closeSessionFactory() { sessionFactory.close(); } } 

这是我的 HibernateUtil.java类:

 import org.hibernate.cfg.Configuration; import org.hibernate.SessionFactory; public class HibernateUtil { private static final SessionFactory sessionFactory; static { try { // Create the SessionFactory from standard (hibernate.cfg.xml) // config file. sessionFactory = new Configuration().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; } public static void closeSessionFactory() { sessionFactory.close(); } } 

这是我的hibernate.cfg.xml

      org.hibernate.dialect.H2Dialect com.mysql.jdbc.Driver jdbc:mysql://localhost:3306/mydatabase user pass  1  org.hibernate.dialect.H2Dialect  org.hibernate.cache.internal.NoCacheProvider  false false false  thread     

我创建会话的代码:

 public class Helper { Session session = null; public Helper() { this.session = HibernateUtil.getSessionFactory().getCurrentSession(); } public List getPeople(int id) { ... } } 

主要方法:

 public static void main(String args[]) { Logger log = Logger.getLogger("org.hibernate"); log.setLevel(Level.WARNING); Helper helper = new Helper(); List people = helper.getPeople(1); for (int i = 0; i < people.size(); i++) { System.out.println("people " + i + ": " + people.get(i).getID()); } HibernateUtil.closeSessionFactory(); } 

你是对的,Hibernate 4.3.x中似乎存在一个错误,其中由Hibernate的默认连接池产生的线程在关闭时不会被清除。 我在这里提交了一个错误(请投票!):

https://hibernate.atlassian.net/browse/HHH-8896

在它修复之前,你有两个选择。 您可以向HibernateUtil添加一个方法,并使用它来强制连接池在应用程序执行结束时自行清理:

 public static void stopConnectionProvider() { final SessionFactoryImplementor sessionFactoryImplementor = (SessionFactoryImplementor) sessionFactory; ConnectionProvider connectionProvider = sessionFactoryImplementor.getConnectionProvider(); if (Stoppable.class.isInstance(connectionProvider)) { ((Stoppable) connectionProvider).stop(); } } 

这是有效的,但是它很难看,hacky,使用不推荐使用的方法等。更好的解决方案是使用“真正的”连接池,如c3p0,只需将以下属性添加到hibernate.cfg即可启用。 XML:

 1 100 10 10 10 100 

请注意,如果您使用其他连接池,则应删除当前位于配置中的此连接池属性:

  1 

编辑:要使用c3p0连接池,你还需要hibernate-c3p0依赖。 来自Hibernate快照repo的4.3.0-SNAPSHOT的Maven示例:

  ...  hibernate-snapshots http://snapshots.jboss.org/maven2/  ...   ...  org.hibernate hibernate-c3p0 4.3.0-SNAPSHOT  ...  

Hibernate版本4.3.5似乎已经解决了这个问题。

 sessionFactory.close(); 

适用于我的计划。

主应用程序终止时释放serviceRegistry。

 public class Service { private SessionFactory factory; private ServiceRegistry serviceRegistry; public void initialize() throws Exception{ Configuration configuration = new Configuration(); configuration.configure("com/jeecourse/config/hibernate.cfg.xml"); serviceRegistry = new StandardServiceRegistryBuilder().applySettings( configuration.getProperties()).build(); factory = configuration.buildSessionFactory(serviceRegistry); } public void close() throws Exception{ if(serviceRegistry!= null) { StandardServiceRegistryBuilder.destroy(serviceRegistry); } }