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

Spring Boot 2.0.1事务回滚失效问题求助

问题排查:Spring Boot + EntityManager 事务回滚失效

问题描述

我正在使用Spring Boot(v2.0.1.RELEASE)结合EntityManager开发,已经花费一周时间处理MySQL数据库异常时的事务回滚问题,但始终无法解决。执行saveUser方法时,虽然抛出了ServiceException,但用户仍然被保存到数据库;当把@Transactional的传播级别改为Propagation.MANDATORY时,直接报错提示没有现有事务。

相关代码

DAO层实现

@Repository
public class HibernateDaoImp implements Dao {
    @PersistenceContext
    private EntityManager entityManager;
    public <T extends AbstractEntity> T saveOrUpdate(T entity) {
        if(entity.getId() == null || entity.getId().equals(0)) {
            this.entityManager.persist(entity);
            t = entity;
        } else {
            t = (T) this.entityManager.merge(entity);
        }
        return t;
    }
}

Service层实现

@Service("userService")
public class UserServiceImp implements UserService {
    @Autowired
    protected Dao dao;
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {ServiceException.class})
    public User saveUser(User user) throws ServiceException {
        user = this.dao.saveOrUpdate(user);
        throw new ServiceException(500, "internal error");
    }
}

修改传播级别后的注解

@Transactional(propagation = Propagation.MANDATORY, rollbackFor = {ServiceException.class})

日志与错误信息

执行saveUser的关键日志

2018-05-25 10:36:46.297 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 为线程[http-nio-8080-exec-4]绑定键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3dd8ed71]对应的值[org.springframework.orm.jpa.EntityManagerHolder@4c6ea9e2]
2018-05-25 10:36:46.356 DEBUG 25041 --- [nio-8080-exec-4] c.s.knected.controller.UserController : save id=null
2018-05-25 10:36:46.357 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 从线程[http-nio-8080-exec-4]获取键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3dd8ed71]对应的值[org.springframework.orm.jpa.EntityManagerHolder@4c6ea9e2]
2018-05-25 10:36:46.358 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 为线程[http-nio-8080-exec-4]绑定键[HikariDataSource (HikariPool-1)]对应的值[org.springframework.jdbc.datasource.ConnectionHolder@5b4dc571]
2018-05-25 10:36:46.358 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 初始化事务同步
2018-05-25 10:36:46.358 TRACE 25041 --- [nio-8080-exec-4] o.s.t.i.TransactionInterceptor : 获取[c.s.k.service.UserServiceImp.saveUser]的事务
2018-05-25 10:36:46.358 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 从线程[http-nio-8080-exec-4]获取键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3dd8ed71]对应的值[org.springframework.orm.jpa.EntityManagerHolder@4c6ea9e2]
Hibernate: insert into user (created_by, time_created, deleted, deleted_by, time_deleted, name, time_updated, updated_by, adress, code, email, password, first_name, lost_login, last_name, mobile, phone, photo_id, time_registered, user_type) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'a')
2018-05-25 10:36:46.457 TRACE 25041 --- [nio-8080-exec-4] o.s.t.i.TransactionInterceptor : 完成[c.s.k.service.UserServiceImp.saveInvite]的事务,已抛出异常c.s.k.service.ServiceException
2018-05-25 10:36:46.457 TRACE 25041 --- [nio-8080-exec-4] o.s.t.i.RuleBasedTransactionAttribute : 应用规则判断事务是否应因c.s.k.service.ServiceException回滚
2018-05-25 10:36:46.457 TRACE 25041 --- [nio-8080-exec-4] o.s.t.i.RuleBasedTransactionAttribute : 生效的回滚规则为:匹配[c.s.k.service.ServiceException]的RollbackRuleAttribute
2018-05-25 10:36:46.460 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 清除事务同步
2018-05-25 10:36:46.460 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 从线程[http-nio-8080-exec-4]移除键[HikariDataSource (HikariPool-1)]对应的值[org.springframework.jdbc.datasource.ConnectionHolder@5b4dc571]
2018-05-25 10:36:46.468 TRACE 25041 --- [nio-8080-exec-4] .s.t.s.TransactionSynchronizationManager : 从线程[http-nio-8080-exec-4]移除键[org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@3dd8ed71]对应的值[org.springframework.orm.jpa.EntityManagerHolder@4c6ea9e2]

改为MANDATORY传播级别时的错误

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

POM配置片段

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

问题分析与解决方案

从你的日志和代码来看,核心问题是事务代理未生效或事务未正确绑定EntityManager,以下是具体排查方向和解决步骤:

1. 确保事务管理被正确启用

虽然Spring Boot默认会自动配置事务管理,但在自定义EntityManagerFactory等场景下,需要显式开启事务管理。在你的Spring Boot启动类上添加@EnableTransactionManagement注解:

@SpringBootApplication
@EnableTransactionManagement
public class YourApplication {
    public static void main(String[] args) {
        SpringApplication.run(YourApplication.class, args);
    }
}

2. 检查事务代理是否生效

改为MANDATORY传播级别时报错,说明@Transactional注解没有被Spring解析,事务代理未创建。常见原因:

  • 服务类未被Spring容器管理:确认UserServiceImp的包被启动类的组件扫描覆盖,且没有通过new关键字手动创建实例。
  • 方法访问权限问题:Spring动态代理无法代理private或final方法,你的saveUser是public的没问题,但要避免同类方法内部调用(会绕过代理)。

3. 验证EntityManager与事务的绑定

显式指定EntityManager的事务上下文类型,确保它和当前事务绑定:

@PersistenceContext(type = PersistenceContextType.TRANSACTION)
private EntityManager entityManager;

4. 检查MySQL数据库的事务支持

MyISAM引擎不支持事务,即使配置了回滚也不会生效。执行以下SQL确认表引擎:

SHOW CREATE TABLE user;

如果是MyISAM,修改为InnoDB:

ALTER TABLE user ENGINE=InnoDB;

5. 确认JPA依赖与配置完整性

检查POM是否包含spring-boot-starter-data-jpa依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

同时确认application.properties中的JPA配置正确:

spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
spring.jpa.show-sql=true
spring.transaction.default-timeout=60

6. 验证异常类型匹配

确保抛出的ServiceException是你在rollbackFor中指定的类,避免出现同名类或子类导致的匹配失败。

快速验证步骤

  1. 给启动类添加@EnableTransactionManagement注解。
  2. 确认MySQL表引擎为InnoDB。
  3. 直接通过Spring容器获取UserService实例调用saveUser,避免同类内部调用。

按照以上步骤排查,应该能解决事务回滚失效的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:04:30