You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成测试报Session/EntityManager关闭异常但应用正常运行如何解决

异常触发原因

第一个异常:IllegalStateException: No transactional EntityManager available

默认通过@PersistenceContext注入的是事务作用域的EntityManager,仅当存在活跃事务上下文时才会完成初始化、处于可用状态。
应用正常运行时,调用formCriteria的上层业务逻辑已经开启了事务,因此EntityManager可以正常使用;而集成测试的调用路径默认没有开启事务上下文,未激活的EntityManager调用unwrap方法就会抛出该异常。

第二个异常:IllegalStateException : Session/EntityManager closed

标注在ReportsUtil类上的@Transactional注解,会为formCriteria方法创建独立事务:事务在方法执行前开启,方法执行结束后自动提交/回滚,同时绑定的EntityManager也会被同步关闭。
你在formCriteria方法内创建的Criteria实例,是和当前事务绑定的Session/EntityManager强关联的,当方法返回、事务结束后,EntityManager已经被回收关闭,后续在ReportRDBMS的executeQueryForSuccess方法中调用criteria.list()时,操作的是已经关闭的Session,因此抛出该异常。
应用正常运行时上层逻辑已经存在事务,ReportsUtil的@Transactional默认会加入已有事务,方法执行结束后不会关闭上层事务绑定的EntityManager,因此不会触发该问题。

解决方案
  • 调整事务边界:移除ReportsUtil类上的@Transactional注解,将@Transactional注解添加到包含完整查询流程的上层方法(即ReportRDBMS的executeQueryForSuccess方法),保证从创建Criteria到执行查询的全流程都处于同一个活跃事务中,EntityManager不会提前关闭。
  • 调整EntityManager作用域:如果业务场景需要在事务外持有EntityManager,可在注入时指定扩展作用域,修改注入注解为@PersistenceContext(unitName = "logs", type = PersistenceContextType.EXTENDED),扩展作用域的EntityManager生命周期和当前持久化上下文绑定,不会随事务结束自动关闭,注意该类型的EntityManager不是线程安全的,不可跨线程共享。
  • 集成测试补充事务配置:如果仅需要解决集成测试的问题,不需要修改业务代码,可直接在集成测试类/测试方法上添加@Transactional注解,让整个测试逻辑运行在统一的事务上下文中,Spring测试默认会在测试结束后自动回滚事务,不会产生脏数据。
  • 封装查询逻辑:修改ReportsUtil的设计,不要返回未执行的Criteria实例,将条件拼接、查询执行的逻辑都封装到ReportsUtil的事务方法内,直接返回最终查询结果,避免外部持有已关闭Session关联的Criteria实例。

内容的提问来源于stack exchange,提问作者Malay Pandey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 09:54:03