我使用 Java 8、Hibernate 5.1.0.Final 和 Guice 4.1.0。
@Inject
private Provider<ExampleDAO> exampleDAOProvider;
public void test(){
ExecutorService threadPool = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++)
threadPool.execute(new Runnable() {
@Override
public void run() {
logger.info(exampleDAOProvider.find(1l));
}
});
threadPool.shutdown();
}
Every test()
方法执行将产生 10(线程池大小)行pg_stat_activity
。它们很简单select * from
查询有idle in transaction
状态并且永远不会消失。所以我达到了hibernate.c3p0.max_size
限制,我的应用程序停止使用数据库。
数据库模块:
public class ExampleModule extends PrivateModule {
@Override
public void configure() {
install(new JpaPersistModule("example-persistence-unit").properties(jpaProperties()));
bind(ExampleDAO.class).to(ExampleDAOImpl.class);
expose(ExampleDAO.class);
Key<PersistFilter> key = Key.get(PersistFilter.class, ExamplePersistenceUnit.class);
bind(key).to(PersistFilter.class);
expose(key);
}
}
我已经尝试过@Inject Provider<ExampleDAO> exampleDAOProvider
进入任务类代码,但它不会改变任何东西。如果我@Inject exampleDAO
,然后我面临并发问题(ConcurrentModificationException
)因为它使用相同的EntityManager
.
如果我使用@Inject Provider<ExampleDAO> exampleDAOProvider
或直接@Inject ExampleDAO exampleDAO
没有多线程,它运行良好并且连接被释放。
为什么会发生这种情况?如何在多线程代码中释放连接?
我已经注释了几乎每个 DAO 方法@Transactional
这似乎解决了我的问题。处理后,提交事务并释放连接。没有标记为@Transactional
查询实体的方法,这些实体稍后应保留在同一实体中EntityManager
or Session
以避免使用merge()
。请注意@Transactional
仅适用于公共方法并且synchronized
不适用于@Transactional
.
通用 DAOImpl 使用@Inject Provider<EntityManager>
代替@Inject EntityManager
:
@Inject
protected Provider<EntityManager> entityManagerProvider;
private EntityManager getEntityManager() {
return entityManagerProvider.get();
}
相关讨论:Guice Persist 是否提供事务范围或应用程序管理的 EntityManager? https://stackoverflow.com/questions/18101488/does-guice-persist-provide-transaction-scoped-or-application-managed-entitymanag
UDPATE 1
其他需要检查的事情:
- 如果您使用 Hibernate 5.1.0.Final,则 persistence.xml 应包含:
<property name="hibernate.connection.provider_class" value="org.hibernate.c3p0.internal.C3P0ConnectionProvider" />
代替:
<property name="connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
UDPATE 2
如果您正在使用
<property name="hibernate.enable_lazy_load_no_trans" value="true" />
延迟加载时可能会导致连接泄漏。相关讨论:
-
org.hibernate.LazyInitializationException - 无法初始化代理 - 无会话 https://stackoverflow.com/questions/21574236/org-hibernate-lazyinitializationexception-could-not-initialize-proxy-no-sess
- 使用 hibernate.enable_lazy_load_no_trans 解决 Hibernate Lazy-Init 问题 https://stackoverflow.com/questions/25362831/solve-hibernate-lazy-init-issue-with-hibernate-enable-lazy-load-no-trans/25367976#25367976
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)