使用hibernate的程序不会终止

我使用Hibernate创build了一个程序。

程序到达主函数结束,不过程序正在运行。

我想知道当SessionFactory使用Hibernate Version 4.x进行configuration时是否会发生这种情况。

configuration的方式错了吗?


manual1_1_first_hibernate_apps.java

 public static void main(String[] args) { args[0] ="list"; if (args.length <= 0) { System.err.println("argement was not given"); return; } manual1_1_first_hibernate_apps mgr = new manual1_1_first_hibernate_apps(); if (args[0].equals("store")) { mgr.createAndStoreEvent("My Event", new Date()); } else if (args[0].equals("list")) { mgr.<Event>listEvents().stream() .map(e -> "Event: " + e.getTitle() + " Time: " + e.getDate()) .forEach(System.out::println); } Util.getSessionFactory().close(); } private <T> List<T> listEvents() { Session session = Util.getSessionFactory().getCurrentSession(); session.beginTransaction(); List<T> events = Util.autoCast(session.createQuery("from Event").list()); session.getTransaction().commit(); return events; } 

Util.java

 private static final SessionFactory sessionFactory; /** * build a SessionFactory */ static { try { // Create the SessionFactory from hibernate.cfg.xml // hibernate version lower than 4.x are as follows // # it successful termination. but buildSessionFactory method is deprecated. // sessionFactory = new Configuration().configure().buildSessionFactory(); // version 4.3 and later // # it does not terminate. I manually terminated. Configuration configuration = new Configuration().configure(); StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); } catch (Throwable ex) { // Make sure you log the exception, as it might be swallowed System.err.println("Initial SessionFactory creation failed." + ex); throw new ExceptionInInitializerError(ex); } } /** * @return built SessionFactory */ public static SessionFactory getSessionFactory() { return sessionFactory; } 

当程序终止并使用buildSessionFactory方法时,以下控制台日志片断。

 2 08, 2014 8:42:25 org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl stop INFO: HHH000030: Cleaning up connection pool [jdbc:derby:D:\Java\jdk1.7.0_03(x86)\db\bin\testdb] 

但如果不使用废弃的buildSessionFactory方法并终止(程序正在运行),则上述两行不会出现。

环境:

 hibernate4.3.1
  DERBY
  JRE 1.8
  IntelliJ IDEA 13

我今天也遇到了这个问题,我发现解决scheme是,在你的主要方法(或线程)的最后,你应该closures你的会话工厂,如:

 sessionFactory.close(); 

然后,你的程序将正常终止。

如果您在主要方法中使用JavaFX 8,则添加:

 @Override public void stop() throws Exception { sessionFactory.close(); } 

此方法将closures会话工厂并销毁程序退出时的线程。

我今天遇到同样的问题,但是我发现了另一个类似的解决scheme:

我在我的代码的末尾插入了以下行:

 StandardServiceRegistryBuilder.destroy(serviceRegistry); 

和Ta-dah! 该程序结束。

同样的问题在4.3.4.Final。

现在添加下面的代码后,问题就没有了。

 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); } } 

…..

看来Hibernate 4.3.1引入了一个bug。 我在我的应用程序中创build连接:

 EntityManagerFactory connection = Persistence.createEntityManagerFactory(...) 

但即使createEntityManagerFactory方法失败并出现exception,服务registry仍保持打开状态。 然而,从上面的代码可以看出,我不能终止我的应用程序,因为由于方法没有成功,variablesconnection没有被赋值(它是空的 ),所以我不能调用connection.close()服务registry。 看来这真的是一个bug,因为我怎样才能释放资源而不诉诸黑客,就像从JPA应用程序中使用特定的Hibernate API?

也许,我解决了这个问题。

在Util.getSessionFactory()。close()调用后看到线程转储,名为“pool-2-thread-1”状态的线程为TIMED_WAITING(parking)。

以下片段转储

 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.0-b69 mixed mode): "DestroyJavaVM" #16 prio=5 os_prio=0 tid=0x00000000020b9000 nid=0x3684 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE "pool-2-thread-1" #15 prio=5 os_prio=0 tid=0x000000001bc27000 nid=0x3f0 waiting on condition [0x000000001ce6f000] java.lang.Thread.State: TIMED_WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x0000000080be30a0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:1093) at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(ScheduledThreadPoolExecutor.java:809) at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1067) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:744) "derby.rawStoreDaemon" #14 daemon prio=5 os_prio=0 tid=0x000000001b059000 nid=0xa3c in Object.wait() [0x000000001ba1f000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon) at org.apache.derby.impl.services.daemon.BasicDaemon.rest(Unknown Source) - locked <0x00000000805f6190> (a org.apache.derby.impl.services.daemon.BasicDaemon) at org.apache.derby.impl.services.daemon.BasicDaemon.run(Unknown Source) at java.lang.Thread.run(Thread.java:744) "Timer-0" #13 daemon prio=5 os_prio=0 tid=0x000000001b08e800 nid=0x2160 in Object.wait() [0x000000001b6af000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000080608118> (a java.util.TaskQueue) at java.lang.Object.wait(Object.java:502) at java.util.TimerThread.mainLoop(Timer.java:526) - locked <0x0000000080608118> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:505) 

我认为原因是由buildSessionFactory方法创build的线程名为“pool-2-thread-1”。

由于比较了两个buildSessionFactory方法,我注意到ServiceRegistry资源还没有发布。

程序通过释放成功终止。

下面的代码,我join。

Util.java

 configuration.setSessionFactoryObserver( new SessionFactoryObserver() { @Override public void sessionFactoryCreated(SessionFactory factory) {} @Override public void sessionFactoryClosed(SessionFactory factory) { ((StandardServiceRegistryImpl) serviceRegistry).destroy(); } } ); 

谢谢。

我刚刚有同样的问题。 我正在使用Hibernate 4.1.1,一切工作正常。 今天我升级到了Hibernate 4.3.1,突然我的应用程序没有终止。 我进一步调查了一下,发现版本4.1.1没有任何问题,打开EntityManagerFactory。 这就是为什么我的应用程序总是终止 版本4.3.1不再是这种情况了。 所以我检查了我的应用程序,并确保EntityManagerFactory在最后closures(实际上我并没有真正closures它)。 问题解决了我。 你确定你的应用程序中没有任何东西可以打开吗? 希望这可以帮助。

马科斯

我今天也遇到了这个问题,我发现解决scheme就像:

 sessionFactory.close(); 

将工作,如果你有

 <property name="connection.pool_size">1</property> 

我有同样的问题,解决scheme是如此简单,你必须将此属性添加到configuration的文件

  <property name="hibernate.c3p0.timeout">0</property> 

我使用hibenate 5.2.12与sqlite 3.20.1,手动pipe理连接。 在我的情况下,问题是不仅实体经理不得不closures,而且实体经理工厂。

有了这些属性:

 EntityManager entityManager; EntityTransaction entityTransaction; 

打开数据库并启动事务时使用此代码片段:

 EntityManagerFactory emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT_NAME, map); entityManager = emf.createEntityManager(map); entityTransaction = entityManager.getTransaction(); entityTransaction.begin(); 

这被剪切用于提交事务并closures数据库:

 entityTransaction.commit(); if ( entityManager.isOpen() ) { entityManager.close(); } EntityManagerFactory emf = entityManager.getEntityManagerFactory(); if ( emf.isOpen() ) { emf.close(); } 

现在用emf.close(); 我的应用程序应该终止。