在Hibernate 4.3中关闭SessionFactory [英] Close SessionFactory in Hibernate 4.3

查看:68
本文介绍了在Hibernate 4.3中关闭SessionFactory的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是我的 HibernateUtil.java 类:

  import org.hibernate.HibernateException; 
导入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);
抛出新的ExceptionInInitializerError(ex);



public static SessionFactory getSessionFactory(){
return sessionFactory;
}

public static void closeSessionFactory(){
sessionFactory.close();
}
}

这是我的 HibernateUtil.java class:

  import org.hibernate.cfg.Configuration ; 
import org.hibernate.SessionFactory;

public class HibernateUtil {

private static final SessionFactory sessionFactory;

static {
try {
//从标准(hibernate.cfg.xml)
// config文件创建SessionFactory。
sessionFactory = new Configuration()。configure()。buildSessionFactory();
} catch(Throwable ex){
//记录异常。
System.err.println(Initial SessionFactory creation failed。+ ex);
抛出新的ExceptionInInitializerError(ex);



public static SessionFactory getSessionFactory(){
return sessionFactory;
}

public static void closeSessionFactory(){
sessionFactory.close();




$ b这是我的 hibernate.cfg.xml

 <?xml version =1.0encoding =UTF-8?> 
<!DOCTYPE hibernate-configuration PUBLIC
- // Hibernate / Hibernate配置DTD 3.0 // EN
http://www.hibernate.org/dtd/hibernate-configuration -3.0.dtd>
< hibernate-configuration>
< session-factory>
<! - 数据库连接设置 - >
< 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>用户< / property>
< property name =hibernate.connection.password> pass< / property>

<! - JDBC连接池(使用内置) - >
< property name =connection.pool_size> 1< / property>

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

<! - 禁用二级缓存 - >
< property name =cache.provider_class> org.hibernate.cache.internal.NoCacheProvider< / property>

<! - 将所有执行的SQL回复到stdout - >
< property name =show_sql> false< / property>
< property name =format_sql> false< / property>
< property name =use_sql_comments> false< / property>


<! - 使用线程作为上下文 - >
< property name =hibernate.current_session_context_class>线程< / property>

<! - 使用这些文件进行映射配置 - >
< mapping resource =test / Person.hbm.xml/>
< / session-factory>
< / hibernate-configuration>

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

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

助手助手=新助手();
列表< Person> people = helper.getPeople(1);

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

HibernateUtil.closeSessionFactory();


解决方案

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

https:

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

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






这个方法可行,但它很丑陋,不推荐使用的方法等。更好的解决方案是只使用真正的连接池,如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>

请注意,如果您使用其他连接池,则应删除当前处于您的连接池属性config:

 <! -  JDBC连接池(使用内置) - > 
< property name =connection.pool_size> 1< / property>编辑:要使用c3p0连接池,您还需要hibernate-c3p0依赖项。

 < repositories>这是一个来自Hibernate快照的4.3.0-SNAPSHOT的Maven示例。 
...
< repository>
< id> hibernate-snapshots< / id>
< url> http://snapshots.jboss.org/maven2/< / url>
< / repository>
...
< / repositories>

<依赖关系>
...
< dependency>
< groupId> org.hibernate< / groupId>
< artifactId> hibernate-c3p0< / artifactId>
< version> 4.3.0-SNAPSHOT< / version>
< /依赖关系>
...
< dependencies>


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

This is my new HibernateUtil.java class:

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 old HibernateUtil.java class:

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:

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

解决方案

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!):

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:

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:

<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:

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

这篇关于在Hibernate 4.3中关闭SessionFactory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆