Java 使用休眠的程序不会终止

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21645516/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:50:22  来源:igfitidea点击:

program using hibernate does not terminate

javahibernate

提问by tomop

I created a program using Hibernate.

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

The program reaches the main function end, nevertheless the program is running.

程序到达 main 函数结束,但程序仍在运行。

I wonder if it happens when SessionFactoryis configured using Hibernate Version 4.x.

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

Is the way to configure wrong?

是不是配置方式不对?



manual1_1_first_hibernate_apps.java

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


The following console log snippets when program terminate and use buildSessionFactory method.

程序终止并使用 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]

but if do not use deprecated buildSessionFactory method and terminated(program is running), the above two lines do not appear.

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

ENVIRONMENT:

环境:

 Hibernate 4.3.1
 DERBY
 JRE 1.8
 IntelliJ IDEA 13

采纳答案by tomop

maybe, I solved this problem.

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

I saw the thread dump after Util.getSessionFactory().close() called, a thread named "pool-2-thread-1" state was TIMED_WAITING (parking).

我在 Util.getSessionFactory().close() 调用之后看到了线程转储,一个名为“pool-2-thread-1”状态的线程是 TIMED_WAITING(停车)。

The following snippets dump

以下片段转储

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)

I thought the cause is thread named "pool-2-thread-1" that created by buildSessionFactory method.

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

As a result of comparing the two buildSessionFactory method, I noticed that ServiceRegistry resources has not released.

对比两个buildSessionFactory方法的结果,发现ServiceRegistry资源没有释放。

Program successfully terminated by releasing it.

程序通过释放成功终止。

The following code, I adding.

下面的代码,我补充。

Util.java

实用程序

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

thanks.

谢谢。

回答by Marcos

I have just had the same problem. I was using Hibernate 4.1.1 and everything was working fine. Today I upgraded to Hibernate 4.3.1 and suddenly my application didn't terminate anymore. I investigated a little further and noticed that version 4.1.1 didn't have any problem with an open EntityManagerFactory. That's why my application always terminated. That's not the case with version 4.3.1 anymore. So I checked my application and made sure that the EntityManagerFactory was closed at the end (indeed I was not really closing it). Problem solved to me. Are you really sure there's nothing left open in your application? Hope this helps.

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

Marcos

马科斯

回答by chuhx

I had the same problem today, but I found another similar solution:

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

I inserted at the end of my code the following line:

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

StandardServiceRegistryBuilder.destroy(serviceRegistry);

And Ta-dah! the program ends.

还有达达!程序结束。

回答by Marcos

It seems that Hibernate 4.3.1 introduced a bug. I create the connection in my application with:

似乎 Hibernate 4.3.1 引入了一个错误。我在我的应用程序中创建连接:

EntityManagerFactory connection = Persistence.createEntityManagerFactory(...)

but even if the createEntityManagerFactorymethod fails with an exception, the service registry remains open. However, as you could see from the above code, I cannot terminate my application because as the method didn't succeed the variable connectionwasn't assigned (it is null), so I cannot call connection.close()that would destroy the service registry. It seems that this is really a bug, because how will I be able to release resources without resorting to a hack, like using specific Hibernate APIs from a JPA application?

但即使该createEntityManagerFactory方法因异常而失败,服务注册表仍保持打开状态。但是,正如您从上面的代码中看到的,我无法终止我的应用程序,因为该方法没有成功,变量connection没有被分配(它是null),所以我不能调用connection.close()它会破坏服务注册表。看起来这确实是一个错误,因为我如何能够在不诉诸黑客的情况下释放资源,例如使用来自 JPA 应用程序的特定 Hibernate API?

回答by Jimmy

Same problem in 4.3.4.Final.

4.3.4.Final 中同样的问题。

Now after adding following code, the problem is gone.

现在添加以下代码后,问题就消失了。

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

.....

.....

回答by Rxxxx

I met this problem also today, and I found the solution is, in the end of your main method (or thread), you should close your Session Factory, like:

我今天也遇到了这个问题,我发现解决方案是,在你的主方法(或线程)结束时,你应该关闭你的会话工厂,比如:

sessionFactory.close();

And then, your program will terminate normally.

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

If You use JavaFX 8 in main method add:

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

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

This method will close session factory and destroy thread on program exit.

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

回答by Sergey Frolov

I met this problem also today, and I found that the solution like:

我今天也遇到了这个问题,我发现解决方案如下:

sessionFactory.close();

will work if you have

如果你有

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

回答by The Appsolit

i had the same problem, the solution is so simple , you have to add this property to configuration's file

我遇到了同样的问题,解决方案很简单,您必须将此属性添加到配置文件中

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

回答by hogi

I am using hibenate 5.2.12 with sqlite 3.20.1, managing the connection manually. In my case the problem was that not only the entity manager had to be closed but also the entity manager factory.

我正在使用带有 sqlite 3.20.1 的 hibenate 5.2.12,手动管理连接。就我而言,问题是不仅实体管理器必须关闭,实体管理器工厂也必须关闭。

With these attributes:

具有这些属性:

EntityManager entityManager;
EntityTransaction entityTransaction;

This snippet is used when opening the DB and starting a transaction:

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

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

This snipped is used to commit the transaction and close the DB:

此片段用于提交事务并关闭数据库:

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

Now with emf.close();my application terminates as is should be.

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

回答by ArifMustafa

My answer is for Hibernate 4.3+ version, and I use it in my way.

我的答案是 Hibernate 4.3+ 版本,我以我的方式使用它。

A example of Spring Annotation configured with Hibernate:

配置 Hibernate 的 Spring Annotation 示例:

//Using AutoCloseable 1.7 feature here to close context and 
//suppress warning Resource leak: 'context' is never closed
//Creating AutoClosebale AbstractApplicationContext Object context
try (AbstractApplicationContext context = new AnnotationConfigApplicationContext(SpringAppConfig.class)) {

    SnacksMenu snacks = context.getBean(SnacksMenu.class);
    System.out.println(snacks.toString());

    //Creating AutoClosebale SessionFactory Object factory
    try (SessionFactory factory = getStandardServiceEnabledSessionFactory()){

        //Creating AutoClosebale Session Object session
        try (Session session = factory.openSession()) {

            SessionCounter.analysisSession(session);
            System.out.println("1: Opened Sessions under factory : " + SessionCounter.getOpenSessionsCount());

            Transaction transaction = session.beginTransaction();

            session.persist(snacks);
            transaction.commit();

            System.out.println(session.isConnected());
        }//Session Object session resource auto closed

    }//SessionFactory Object factory resource auto closed

    System.out.println("2: Opened Sessions under factory : " + SessionCounter.getOpenSessionsCount());

}//AbstractApplicationContext Object context resource auto closed