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

执行Update/Delete查询触发javax.persistence.TransactionRequiredException问题

解决javax.persistence.TransactionRequiredException执行更新/删除查询异常

我之前也踩过这个坑,结合你给出的异常栈信息,咱们来拆解下问题根源和对应的解决办法:

首先先把你遇到的异常栈贴出来方便参考:

javax.persistence.TransactionRequiredException: Executing an update/delete query 
at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1496) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final] 
at org.springframework.data.jpa.repository.query.JpaQueryExecution$ModifyingExecution.doExecute(JpaQueryExecution.java:256) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:91) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:136) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:125) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:590) ~[spring-data-commons-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578) ~[spring-data-commons-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59) ~[spring-data-commons-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) ~[spring-tx-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) ~[spring-tx-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) ~[spring-data-jpa-2.0.5.RELEASE.jar:2.0.5.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61) ~[spring-data-commons-2.0.5.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at com.sun.proxy.$Proxy93.existProjectTasks(Unknown Source) ~[na:na] 
at ca.projectmanagementapis.projectmanagementproject.daoImplementation.ProjectManagementAPIsReadMethodsDAO.getProjectTaskExist(ProjectManagementAPIsReadMethodsDAO.java:271) ~[classes/:na] 
at ca.projectmanagementapis.projectmanagementproject.daoImplementation.ProjectManagementAPIsReadMethodsDAO$$FastClassBySpringCGLIB$$c3d37619.invoke(<generated>) ~[classes/:na] 
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:747) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) ~[spring-tx-5.0.4.RELEASE.jar:5.0.4.RELEASE] 
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) ~[spring-aop-5.0.4.RELEASE.jar:5.0.4.RELEASE]

异常原因分析

这个异常的核心是:当你执行更新/删除类型的JPQL查询时,当前线程没有绑定活跃的数据库事务。从你的调用链能看到,虽然Spring的TransactionInterceptor已经在调用链里,但事务并没有正确生效,常见的触发场景有这几种:

  1. Spring Data JPA的Repository接口中,执行更新/删除的方法缺少@Modifying和@Transactional注解
  2. 事务注解的传播行为配置错误(比如用了SUPPORTS/NOT_SUPPORTED,不会主动开启事务)
  3. 调用Repository的上层方法(比如你的ProjectManagementAPIsReadMethodsDAO.getProjectTaskExist)没有事务,且Repository的事务注解因为Spring AOP代理问题没生效
  4. 自定义DAO实现类中直接调用EntityManager执行更新,但没在事务上下文里

具体解决办法

针对上述场景,一一对应解决:

1. 给Repository的修改方法补全注解

如果是Spring Data JPA的Repository接口方法,必须同时添加@Modifying(告诉Spring这是修改类查询)和@Transactional(开启事务):

@Repository
public interface TaskRepository extends JpaRepository<Task, Long> {
    // 示例:删除指定项目下的任务
    @Modifying
    @Transactional
    @Query("DELETE FROM Task t WHERE t.projectId = :projectId")
    void deleteTasksByProjectId(@Param("projectId") Long projectId);
}

注意:@Transactional可以加在Repository方法上,也可以加在调用它的Service层方法上(更推荐,因为事务通常在业务层管控)。

2. 检查事务传播行为

确保你的@Transactional注解的propagation属性是默认的REQUIRED(如果没有手动配置,默认就是这个),不要用SUPPORTS或者NOT_SUPPORTED——这俩不会主动开启新事务,只有当已有事务存在时才会加入。

3. 确保Spring AOP能代理到你的类

看你的异常栈,调用了自定义DAO类ProjectManagementAPIsReadMethodsDAO的方法,要确保:

  • 这个类被Spring容器管理(加了@Repository或者@Component注解)
  • 如果这个类的方法直接调用了需要事务的更新/删除操作,要么在该方法上加@Transactional,要么在调用它的Service层方法上加@Transactional

比如你的getProjectTaskExist方法如果内部触发了更新/删除,就给它加注解:

@Repository
public class ProjectManagementAPIsReadMethodsDAO {
    @Autowired
    private TaskRepository taskRepository;

    @Transactional // 加上这个注解,确保方法在事务内执行
    public boolean getProjectTaskExist(Long projectId) {
        // 这里调用taskRepository的修改方法,或者自己用EntityManager执行更新
        return taskRepository.existsByProjectId(projectId);
    }
}

4. 手动使用EntityManager时要确保在事务内

如果是直接用EntityManager执行更新/删除,必须在事务方法内调用:

@Transactional
public void updateTaskStatus(Long taskId, String newStatus) {
    entityManager.createQuery("UPDATE Task t SET t.status = :status WHERE t.id = :taskId")
            .setParameter("status", newStatus)
            .setParameter("taskId", taskId)
            .executeUpdate();
}

5. 确认Spring事务配置已开启

最后检查下你的Spring配置:

  • 如果是Java配置类,要加@EnableTransactionManagement注解
  • 如果是XML配置,要添加<tx:annotation-driven/>标签

这样Spring才能识别@Transactional注解并创建事务代理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:02:42