我最近開始在應用程序中使用hibernate和c3p0作爲ORM。但是,當我關閉會話工廠時,連接池不會自動關閉!這是唯一的地方在我的應用程序,我做任何事情與會議。休眠:關閉會話工廠不關閉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仍嘗試在開始時打開兩個連接。我的猜測是某種隱藏的會話不會關閉(但是在哪裏?打敗我)。
那麼,如何才能讓煩人的連接池關閉?
附加信息: 我如何創建和銷燬我的會話工廠
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 2013-03-08 16:46:25
SessionFactory在我的一些集成測試之間關閉並重新啓動,以避免可能影響它們的延遲狀態。我也關閉了我的WebServer,關閉了一些Unix Socket連接,放下測試數據庫......一切都是真的。當我開始第二次測試時,它應該是純淨的。當然,在製作過程中,我不會花時間關閉和重新開始那些事情,那樣會毫無用處。每個hibernate的文檔都有 – 2013-03-08 16:55:47
,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管理一堆被中斷的線程,並在關閉時清理東西,必須返回未完成的cxns – 2013-03-09 08:20:34