Spring Boot 3.0.0使用query.executeUpdate()遇TransactionRequiredException问题
针对你遇到的添加了@Transactional注解但执行JPQL更新操作仍抛出TransactionRequiredException的问题,可从以下几个方向排查解决:
1. 确认事务代理是否正常生效
Spring事务基于动态代理实现,只有外部类调用public方法时才会触发事务。如果UpdatePassageByNiveau是被同一个PassageService类内的其他方法调用,事务注解不会生效。
解决方式:确保通过注入的PassageService实例从外部调用该方法(比如在Controller层调用)。
另外,可在启动类显式添加@EnableTransactionManagement注解(Spring Boot默认已开启,但显式声明可避免配置异常):
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.transaction.annotation.EnableTransactionManagement; @SpringBootApplication @EnableTransactionManagement public class YourApplication { public static void main(String[] args) { SpringApplication.run(YourApplication.class, args); } }
2. 检查EntityManager的事务绑定
确保@PersistenceContext注入的EntityManager是容器管理的实例。Spring Boot 3中默认配置下,容器会自动将EntityManager与当前事务绑定,但如果存在自定义的EntityManager配置,可能导致事务关联失败。
若排查需要,可尝试替换为@Autowired注入EntityManagerFactory,手动获取事务绑定的EntityManager:
@Autowired private EntityManagerFactory entityManagerFactory; @Transactional public void UpdatePassageByNiveau(int niveau, String cin) { EntityManager em = entityManagerFactory.createEntityManager(); // ... 原有代码逻辑 }
注:更推荐保持@PersistenceContext注入方式,容器管理的EntityManager更省心,此方法仅作为临时排查手段。
3. 修正JPQL语句的语法错误
虽然这不是事务异常的直接原因,但你的JPQL语句存在语法问题:WHERE resident.cin = :cin中的resident未关联到Passage对象,应改为p.resident.cin = :cin(假设Passage类有resident属性),否则会先抛出JPQL语法异常:
String queryRecherche = "UPDATE Passage p SET p.dateDebut = p.dateDebut + 1 year, p.dateFin = p.dateFin + 1 year WHERE p.resident.cin = :cin and p.niveau = :niveau ";
4. 检查依赖与配置
确保项目依赖中正确引入了Spring Data JPA,它包含了事务管理所需的核心组件:
<!-- Maven依赖示例 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency>
内容的提问来源于stack exchange,提问作者ayada

