最近アプリケーションで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
なぜあなたは接続プールを閉じますか?閉じていると新しい接続を選択することはできません。 – dotvav
SessionFactoryは、状態に影響を与える可能性のある状態を避けるために、いくつかの統合テストの間に閉じられ、再開されます。 Webサーバーを閉じて、Unixソケット接続を閉じ、テストデータベースを削除してください。本当にすべてです。私が2回目のテストを開始するとき、それはきれいで清潔でなければなりません。もちろん、制作には時間をかけずにこれらのものを再起動しますが、それはかなり役に立たないでしょう。 –
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は中断されたスレッドの束を管理し、終了時にはクリーンなものを返す必要があります。 –