我们有一个使用 Hibernate 连接到 postgre 数据库的应用程序。我们使用 C3P0 作为连接池。
持久性.xml:
<persistence-unit name="tv-europe-core" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider>
---课程---
<properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
<property name="hibernate.connection.password" value="---password---" />
<属性名称="hibernate.connection.url" value="---数据库---" />
<property name="hibernate.connection.username" value="---用户名---" /><property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.connection.release_mode" value="after_statement" />
<property name="hibernate.connection.autocommit " 值="假" /><property name="hibernate.c3p0.minPoolSize" value="5"/>
<property name="hibernate.c3p0.maxPoolSize" value="60"/>
<property name="hibernate.c3p0.maxIdleTime" value=" 10"/>
<property name="hibernate.c3p0.idleConnectionTestPeriod" value="5"/>
<property name="hibernate.c3p0.testConnectionOnCheckin" value="true"/>
</properties>
</persistence-unit>
保存对象:
public Entity saveOrUpdate(Entity entity, User u) { EntityTransaction tx = EntityManagerHelper.getEntityManager().getTransaction(); try { if(!tx.isActive()) tx.begin(); Entity result = null; if (getID(entity) == null) { EntityManagerHelper.getEntityManager().persist(entity); } else { result = EntityManagerHelper.getEntityManager().merge(entity); } tx.commit(); return result; } catch (RuntimeException re) { re.printStackTrace(); tx.rollback(); throw re; } }
加载对象:
@SuppressWarnings("unchecked")
public List<Entity> findByProperty(String propertyName, final Object value,
final int... rowStartIdxAndCount) {
try {
final String queryString = "select model from " + clazz.getName()
+ " model where model." + propertyName + "= :propertyValue";
Query query = EntityManagerHelper.getEntityManager().createQuery(
queryString);
query.setParameter("propertyValue", value);
if (rowStartIdxAndCount != null && rowStartIdxAndCount.length > 0) {
int rowStartIdx = Math.max(0, rowStartIdxAndCount[0]);
if (rowStartIdx > 0) {
query.setFirstResult(rowStartIdx);
}
if (rowStartIdxAndCount.length > 1) {
int rowCount = Math.max(0, rowStartIdxAndCount[1]);
if (rowCount > 0) {
query.setMaxResults(rowCount);
}
}
}
final List<Entity> result = query.getResultList();
return result;
} catch (RuntimeException re) {
re.printStackTrace();
throw re;
}
}
创建 EntityManagerFactory 并获取 EntityManager:
private static EntityManagerFactory emf;
private static final ThreadLocal<EntityManager> threadLocal = new ThreadLocal<EntityManager>();
public static EntityManager getEntityManager() throws HibernateException {
EntityManager session = (EntityManager) threadLocal.get();
if (session == null || !session.isOpen()) {
session = (emf != null) ? emf.createEntityManager()
: null;
threadLocal.set(session);
}
return session;
}
问题是,一个数据库连接一次又一次地停留在“事务中的空闲”状态,之后这个连接就永远不会返回。几天后,应用程序停止响应,因为连接数超过了池的最大大小。
启用 hibernate hibernate.connection.autocommit 后,这些连接不会变成“事务中的空闲”,但它们仍然以某种方式被阻塞,并且产生的问题是相同的。
我们是否做错了什么(一些缺少配置等)?
我注意到,当我只使用急切加载时,没有问题。但由于性能,我必须使用延迟加载。EntityManagerFactory 是否应该显式关闭?我希望不会,因为我们需要应用程序运行很长时间,而且我怀疑当有人使用持久对象时我不能重置它。
在日志中我看到以下内容,但我不知道它是否与我们的问题有关:
java.lang.Exception: DEBUG -- CLOSE BY CLIENT STACK TRACE
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:491)
at com.mchange.v2.c3p0.impl.NewPooledConnection.close(NewPooledConnection.java:191)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.dest royResource(C3P0PooledConnectionPool.java:470)
at com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask.run(BasicResourcePool.ja va:964)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunn er.java:547)
谢谢你的帮助!:)