Java 在 Hibernate 4.3 中关闭 SessionFactory

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20976322/
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 05:41:06  来源:igfitidea点击:

Close SessionFactory in Hibernate 4.3

javahibernate

提问by ThreaT

I'm upgrading my Hibernate to the latest version. With my old HibernateUtil.javaI had no problems but when upgrading it, the SessionFactory doesn't seem to close anymore.

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

This is my newHibernateUtil.javaclass:

这是我的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();
    }
}

This is my oldHibernateUtil.javaclass:

这是我的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();
    }
}

This is my hibernate.cfg.xml:

这是我的hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <!-- Database connection settings -->
        <property name="hibernate.dialect">org.hibernate.dialect.H2Dialect</property>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydatabase</property>
        <property name="hibernate.connection.username">user</property>
        <property name="hibernate.connection.password">pass</property>

        <!-- JDBC connection pool (use the built-in) -->
        <property name="connection.pool_size">1</property>

        <!-- SQL dialect -->
        <property name="dialect">org.hibernate.dialect.H2Dialect</property>

        <!-- Disable the second-level cache  -->
        <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property>

        <!-- Echo all executed SQL to stdout -->
        <property name="show_sql">false</property>
        <property name="format_sql">false</property>
        <property name="use_sql_comments">false</property>


        <!-- Use the thread as the context -->
        <property name="hibernate.current_session_context_class">thread</property>

        <!-- Use these files for mapping configuration -->
        <mapping resource="test/Person.hbm.xml"/>
    </session-factory>
</hibernate-configuration>

Code in which I create the session:

我在其中创建会话的代码:

public class Helper {

    Session session = null;

    public Helper() {
        this.session = HibernateUtil.getSessionFactory().getCurrentSession();
    }

    public List getPeople(int id) {
       ...
    }
}

Main method:

主要方法:

public static void main(String args[]) {
    Logger log = Logger.getLogger("org.hibernate");
    log.setLevel(Level.WARNING);

    Helper helper = new Helper();
    List<Person> people = helper.getPeople(1);

    for (int i = 0; i < people.size(); i++) {
        System.out.println("people " + i + ": " + people.get(i).getID());
    }

    HibernateUtil.closeSessionFactory();
}

采纳答案by Shane

You're right, there appears to be a bug in Hibernate 4.3.x in which a thread spawned by Hibernate's default connection pool doesn't get cleaned up on shutdown. I filed a bug here (please vote!):

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

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

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

Until it's fixed, you have two choices. You can add a method to your HibernateUtil and use it to force the connection pool to clean itself up at the end of your app's execution:

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

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

This works, but it's ugly, hacky, uses a deprecated method, etc. The better solution would be to just use a "real" connection pool, like c3p0, which can be enabled just by adding the following properties to your hibernate.cfg.xml:

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

<property name="hibernate.c3p0.acquire_increment">1</property>
<property name="hibernate.c3p0.idle_test_period">100</property>
<property name="hibernate.c3p0.max_size">10</property>
<property name="hibernate.c3p0.max_statements">10</property>
<property name="hibernate.c3p0.min_size">10</property>
<property name="hibernate.c3p0.timeout">100</property>

Note that if you use another connection pool, you should remove this connection pool property which is currently in your config:

请注意,如果您使用另一个连接池,则应删除当前在您的配置中的此连接池属性:

<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">1</property>

Edit: to use c3p0 connection pooling you'll also need the hibernate-c3p0 dependency. Maven example for 4.3.0-SNAPSHOT from the Hibernate snapshots repo:

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

<repositories>
  ...
  <repository>
    <id>hibernate-snapshots</id>
    <url>http://snapshots.jboss.org/maven2/</url>
  </repository>
  ...
</repositories>

<dependencies>
 ...
 <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-c3p0</artifactId>
   <version>4.3.0-SNAPSHOT</version>
 </dependency>
 ...
<dependencies>

回答by Jimmy

Release the serviceRegistry when the main application terminates.

当主应用程序终止时释放 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);
    }
}

回答by Serge Rogatch

The issue seems to be already solved in Hibernate version 4.3.5 .

这个问题似乎已经在 Hibernate version 4.3.5 中解决了。

sessionFactory.close();

works in my program.

在我的程序中工作。