我的应用程序使用JPA和Hibernate作为提供程序,以及Spring管理的本地事务。
为了维护“长时间运行的持久性上下文”或对话,EntityManager在Web层上创建一次(在用例的开头)(通过调用EntityManagerFactory.createEntityManager()
),并且存储在HttpSession中。 EntityManagerFactory是一个代理,它将在事务中调用时返回相同的EntityManager。因此,DAO访问相同的EntityManager以使用JpaTemplate执行CRUD操作。这一切都很好。
但是,我注意到连接池的错误已经耗尽,并找出原因:某些实体具有延迟加载关系,最终在网页呈现期间加载(#{person.address.street}
等字段)。
当一些HttpSession处于活动状态时,所有这一切都正常,因为EntityManager在事务结束后仍保持打开状态。随着越来越多的用户连接到应用程序,池会耗尽,因为一旦执行了从Web触发的查询,Hibernate实际上不会释放与池的连接。
Hibernate连接释放模式设置为auto
,这意味着(对于具有本地事务的tomcat)after_transaction
。但是,由于在Web层中执行查询时没有事务,因此Hibernate在完成工作后不会释放与池的连接。它实际上是在EntityManager关闭时释放它。
Hibernate连接释放模式可以是after_statement
或after_transaction
或on_close
,但它们都不适合在事务内外进行查询(after_statement
只应该用于JTA)。
所以,问题是“为了能够在Web层和长期运行的持久化上下文中使用延迟加载关系,我应该更改什么?”