使用hibernate的程序不会终止

max*_*ead 42 java hibernate

我用Hibernate创建了一个程序.

程序到达主函数端,但程序正在运行.

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

是配置错误的方法?


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;
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

程序终止时使用以下控制台日志片段并使用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]
Run Code Online (Sandbox Code Playgroud)

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

环境:

 Hibernate 4.3.1
 DERBY
 JRE 1.8
 IntelliJ IDEA 13

小智 47

我今天也遇到了这个问题,我发现解决方案是,在你的主方法(或线程)的最后,你应该关闭你的Session Factory,如:

sessionFactory.close();
Run Code Online (Sandbox Code Playgroud)

然后,您的程序将正常终止.

如果在main方法中使用JavaFX 8,请添加:

@Override
public void stop() throws Exception {
    sessionFactory.close();
}
Run Code Online (Sandbox Code Playgroud)

此方法将关闭会话工厂并在程序退出时销毁线程.


chu*_*uhx 14

我今天遇到了同样的问题,但我找到了另一个类似的解决方案:

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

StandardServiceRegistryBuilder.destroy(serviceRegistry);
Run Code Online (Sandbox Code Playgroud)

和Ta-dah!该计划结束.


Jim*_*mmy 7

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

.....


max*_*ead 5

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

我在Util.getSessionFactory().close()调用后看到了线程转储,名为"pool-2-thread-1"状态的线程是TIMED_WAITING(停放).

以下代码段转储

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)
Run Code Online (Sandbox Code Playgroud)

我认为原因是由buildSessionFactory方法创建的名为"pool-2-thread-1"的线程.

作为比较两个buildSessionFactory方法的结果,我注意到ServiceRegistry资源尚未发布.

程序通过发布成功终止.

我添加了以下代码.

Util.java

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

谢谢.