SpringBoot 2.7.0无@Transactional执行Select查询报无事务EntityManager异常
问题根因
这个问题是Spring Boot 2.7.0依赖的Spring Data JPA 2.7.0版本引入的隐式行为变更导致的,该变更没有出现在Spring Boot 2.7.0的官方发布说明里:
- 2.6.x及更早版本中,Spring Data JPA会给所有Repository查询方法(包括
@Query标注的自定义JPQL查询)隐式创建只读事务,不需要手动加@Transactional就能拿到绑定事务的EntityManager正常执行。 - 2.7.0版本调整了事务自动判定逻辑:带嵌套子查询的自定义JPQL查询不会再被默认识别为只读查询,框架不会给这类方法自动开启事务,执行时就会抛出「No transactional EntityManager available」异常。
这个变更本来是为了修复旧版本bug——框架会给带写操作、锁逻辑的复杂关联查询、存储过程调用错误开启只读事务导致执行失败,但没有兼容纯只读的子查询场景,造成了版本升级兼容性问题。
修复方案
两种方案都可以解决问题,按需选择即可:
- 方案1(推荐):在出问题的查询方法,或者对应Repository接口上加
@Transactional(readOnly = true)注解,显式声明方法的事务属性。这种写法最稳妥,后续版本升级不会再因为框架隐式逻辑调整出现同类问题。 - 方案2:如果项目里这类子查询很多,不想逐个加注解,可以添加全局配置把Spring Data JPA的Repository默认事务行为改回旧版本逻辑:
spring: data: jpa: repositories: default-transaction-type: read-only
properties格式配置写法:
spring.data.jpa.repositories.default-transaction-type=read-only
验证结果
添加完注解或者修改完配置重启应用,原JPQL查询不需要调整业务逻辑就能正常执行,和2.6.7版本行为完全一致。
内容的提问来源于stack exchange,提问作者Helotrix
相关产品推荐
相关产品推荐

