2013-03-08 23 views
8

最近アプリケーションでORMとしてc3p0とともにhibernateを使用し始めました。ただし、セッションファクトリを閉じると、接続プールは閉じません。これは私のアプリケーションでは私がセッションで何かを行う唯一の場所です。Hibernate:セッションファクトリを閉じてもc3p0接続プールが閉じない

StatelessSession session = null; 
    Transaction transaction = null; 


    try { 
     session = sessionFactory.openStatelessSession(); 
     transaction = session.beginTransaction(); 

     List<Thingy> list = session.getNamedQuery("getAvailableThingy").list(); 

     transaction.commit(); 
     return list; 

    } catch (Exception error) { 
     if (transaction != null) { 
      transaction.rollback(); 
     } 
     throw error; 
    } finally { 
     if (session != null) { 
      session.close(); 
     } 
    } 

これは私のhibernate.cfg.xml設定ファイルの唯一の方法は、非常に短いアイドル接続その理由は、私は私の統合テストを通過させるためにまだ見つかっていること

<?xml version='1.0' encoding='utf-8'?> 
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD//EN" 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 


<hibernate-configuration> 
    <session-factory> 
     <property name="hibernate.connection.driver_class">org.postgresql.Driver</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property> 
     <property name="javax.persistence.validation.mode">none</property> 
     <property name="hibernate.connection.release_mode">after_transaction</property> 

     <property name="hibernate.c3p0.minPoolSize">1</property> 
     <property name="hibernate.c3p0.maxPoolSize">2</property> 
     <property name="hibernate.c3p0.acquireIncrement">1</property> 
     <property name="hibernate.c3p0.initialPoolSize">1</property> 
     <property name="hibernate.c3p0.timeout">30</property> 
     <property name="hibernate.c3p0.maxIdleTimeExcessConnections">5</property> 
     <property name="hibernate.c3p0.idleConnectionTestPeriod">300</property> 
    </session-factory> 
</hibernate-configuration> 

注意です。彼らはセッションファクトリーをたくさん開いたり閉じたりするので、私はいつもコネクションを使い果たしてしまいます。私たちはプロジェクトの始めにいるので、長期的には非常に持続可能な戦略ではないと思います。

"興味深い"ことは、最初の接続プールを1に設定しても、c3p0はまだ開始時に2つの接続を開こうとすることです。私の推測では、閉鎖されていないどこかの隠れたセッションがあるということです(しかし、どこに?私を打つ)。

それで、どうやってその厄介な接続プールを閉鎖することができますか?

追加情報: 私は私のセッションファクトリ

import static com.google.common.base.Preconditions.*; 

import javax.inject.Inject; 
import javax.inject.Provider; 
import javax.inject.Singleton; 
import org.hibernate.SessionFactory; 
import org.hibernate.cfg.Configuration; 
import org.hibernate.service.ServiceRegistry; 
import org.hibernate.service.ServiceRegistryBuilder; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

import com.google.inject.Provides; 


@Singleton 
public class PostgisConnection implements Provider<SessionFactory>, AutoCloseable { 
    private final Logger logger = LoggerFactory.getLogger(getClass()); 
    private final ConnectionInfo connectionInfo; 
    private SessionFactory sessionFactory = null; 

    @Inject 
    public PostgisConnection(ConnectionInfo connectionInfo) { 
     this.connectionInfo = connectionInfo; 
    } 

    public AutoCloseable open() { 
     checkState(sessionFactory == null, "Connections to postgis are already open"); 

     logger.info("Creating sessionFactory for connection to postgis: {}", connectionInfo.getJdbcUrl()); 
     sessionFactory = newPostgisSessionFactory(connectionInfo); 

     return this; 
    } 

    @Override 
    public void close() throws Exception { 
     try { 
      if (sessionFactory != null) { 
       logger.info("Closing sessionFactory for postgis: {}", connectionInfo.getJdbcUrl()); 
       sessionFactory.close(); 
       checkState(sessionFactory.isClosed(), "Session factory should be closed at this point"); 
      } 
     } catch (Exception error) { 
      logger.error("Error closing SessionFactory", error); 
     } 
    } 

    @Provides 
    public SessionFactory get() { 
     return sessionFactory; 
    } 

    public static SessionFactory newPostgisSessionFactory(ConnectionInfo connectionInfo) { 
     Configuration configuration = configurationWith(connectionInfo); 
     return configuration.buildSessionFactory(registryFrom(configuration)); 
    } 

    private static Configuration configurationWith(ConnectionInfo connectionInfo) { 
     Configuration configuration = new Configuration(); 
     setConnectionInfo(connectionInfo, configuration); 
     configuration.addURL(PostgisConnection.class.getResource("mapping.hbm.xml")); 
     configuration.configure(PostgisConnection.class.getResource("hibernate.cfg.xml")); 

     return configuration; 
    } 

    private static void setConnectionInfo(ConnectionInfo connectionInfo, Configuration configuration) { 
     configuration.setProperty("hibernate.connection.url", connectionInfo.getJdbcUrl()); 
     configuration.setProperty("hibernate.connection.username", connectionInfo.getUsername()); 
     configuration.setProperty("hibernate.connection.password", connectionInfo.getPassword()); 
    } 

    private static ServiceRegistry registryFrom(Configuration configuration) { 
     return new ServiceRegistryBuilder() 
       .applySettings(configuration.getProperties()) 
       .buildServiceRegistry(); 
    } 

} 
  • Hibernateのバージョンの作成および破棄方法:4.1.10.Finalを
  • C3P0バージョン:0.9.1.2
+0

なぜあなたは接続プールを閉じますか?閉じていると新しい接続を選択することはできません。 – dotvav

+0

SessionFactoryは、状態に影響を与える可能性のある状態を避けるために、いくつかの統合テストの間に閉じられ、再開されます。 Webサーバーを閉じて、Unixソケット接続を閉じ、テストデータベースを削除してください。本当にすべてです。私が2回目のテストを開始するとき、それはきれいで清潔でなければなりません。もちろん、制作には時間をかけずにこれらのものを再起動しますが、それはかなり役に立たないでしょう。 –

+0

hibernateのドキュメントごとに、SessionFactor.close()はプールを閉じます。 "このSessionFactoryを破棄し、すべてのリソース(キャッシュ、接続プールなど)を解放してください。 [http://docs.jboss.org/hibernate/orm/4.1/javadocs/org/hibernate/SessionFactory.html]期待通りに呼び出されるclose()メソッドがログに記録されますか?いくつかのアイデア:1)c3p0-0.9.1.2は少し長いですが、かなり成熟したc3p0-0.9.2にアップグレードしてみてください。 2)c3p0 close()は必ずしも瞬間的なものではないことに注意してください。c3p0は中断されたスレッドの束を管理し、終了時にはクリーンなものを返す必要があります。 –

答えて

13

私が持っていました同じ問題と成功した回避策を提供in this bug report

private void closeSessionFactory(SessionFactory factory) { 
    if(factory instanceof SessionFactoryImpl) { 
     SessionFactoryImpl sf = (SessionFactoryImpl)factory; 
     ConnectionProvider conn = sf.getConnectionProvider(); 
     if(conn instanceof C3P0ConnectionProvider) { 
     ((C3P0ConnectionProvider)conn).close(); 
     } 
    } 
    factory.close(); 
} 

hibernate-c3p0-4.x.x jarを参照する必要があります。

+0

ありがとう、私たちはもう少し複雑な作業に終わった、それは便利だろう。 –

0

私は同じ問題を持っていたし、正常ehnancedを使用(2014年1月)は、回避策in this bug reportを提供:

private static boolean closeSessionFactoryIfC3P0ConnectionProvider(SessionFactory factory) { 

    boolean done = false; 
    if(factory instanceof SessionFactoryImpl) { 
     SessionFactoryImpl sf = (SessionFactoryImpl)factory; 
     ConnectionProvider conn = sf.getConnectionProvider(); 
     if(conn instanceof C3P0ConnectionProvider) { 
      ((C3P0ConnectionProvider)conn).close(); 
      try { 
       Thread.sleep(2000); //Let give it time...it is enough...probably 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      done = true; 
     } 
     factory.close(); 
    } 
    return done; 

} 

あなたは休止状態-c3p0-4.x.x jarファイルを参照する必要があります。