Spring Boot 企业级事务设计规范(90% 项目都会踩的坑)
在企业级 Spring Boot 项目中,@Transactional 是最常用但最容易被误用的注解之一。
很多系统上线后才发现:
- 事务根本没有生效
- 数据部分提交
- 分布式锁 + 事务顺序错误
- MyBatis 自动提交
本文总结一套 企业级事务设计规范,包含:
1️⃣ @Transactional 8 大常见失效场景
2️⃣ 事务传播最佳实践
3️⃣ MyBatis + Spring 事务机制原理
4️⃣ 分布式锁 + 事务顺序问题
一、Spring 事务架构
Spring 事务本质是 AOP + 数据源事务管理器。
执行流程:
调用 Service 方法
↓
Spring AOP 拦截
↓
开启事务
↓
执行 SQL
↓
成功 → commit
异常 → rollback
二、@Transactional 8 大常见失效场景
这是生产事故最多的 8 种情况。
1 同类方法调用(最常见)
事务依赖 AOP代理。
如果在同一个类中调用事务方法:
@Service
public class UserService {
public void methodA() {
methodB(); // 事务不会生效
}
@Transactional
public void methodB() {
userMapper.insert();
}
}
原因:
解决方案:
@Autowired
private UserService userService;
public void methodA(){
userService.methodB(); // 通过代理调用
}
或:
AopContext.currentProxy()
2 方法不是 public
Spring 默认只代理 public 方法。
错误示例:
@Transactional
private void saveUser(){
}
正确:
@Transactional
public void saveUser(){
}
3 捕获异常但没有抛出
Spring 只在 异常抛出 时回滚。
错误示例:
@Transactional
public void createOrder(){
try{
orderMapper.insert();
int a = 1 / 0;
}catch(Exception e){
log.error(e);
}
}
结果:
订单数据提交成功
正确写法:
catch(Exception e){
throw new RuntimeException(e);
}
或者:
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
4 异常不是 RuntimeException
Spring 默认只回滚:
RuntimeException
Error
不会回滚:
CheckedException
错误示例:
@Transactional
public void test() throws Exception {
throw new Exception("error");
}
解决:
@Transactional(rollbackFor = Exception.class)
5 Controller 层加事务
很多人这样写:
@RestController
public class OrderController {
@Transactional
@PostMapping("/create")
public void create(){
orderService.create();
}
}
问题:
- Controller 事务范围太大
- HTTP逻辑 + DB逻辑混合
正确:
事务放在:
@Service
public class OrderService {
@Transactional
public void create(){
orderMapper.insert();
}
}
6 使用 new 创建对象
错误示例:
UserService userService = new UserService();
userService.save();
Spring AOP 无法代理:
事务失效
必须:
@Autowired
UserService userService;
7 多线程调用
@Transactional
public void createOrder(){
new Thread(() -> {
orderMapper.insert();
}).start();
}
事务只在当前线程有效。
8 final 方法
Spring 默认 JDK/CGLIB 代理
final 方法无法被代理:
@Transactional
public final void save(){
}
事务失效。
三、事务传播机制
事务传播用于:
事务嵌套
微服务调用
日志记录
补偿操作
Spring 支持 7 种传播行为。
| 传播级别 | 说明 |
|---|---|
| REQUIRED | 默认,加入当前事务 |
| REQUIRES_NEW | 新事务 |
| SUPPORTS | 有事务就加入 |
| NOT_SUPPORTED | 不使用事务 |
| MANDATORY | 必须有事务 |
| NEVER | 不能有事务 |
| NESTED | 嵌套事务 |
推荐企业实践
1 默认使用 REQUIRED
@Transactional
public void createOrder(){
}
2 日志使用 REQUIRES_NEW
保证日志一定提交。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(){
}
架构:
即使主事务回滚:
日志仍然存在
3 审计记录
REQUIRES_NEW
适用于:
操作日志
审计日志
系统日志
四、MyBatis + Spring 事务机制
很多人误以为:
MyBatis 自动管理事务
实际上:
Spring 管理事务
MyBatis 只执行 SQL
架构:
关键组件:
DataSourceTransactionManager
SqlSessionTemplate
SqlSessionTemplate
Spring 会自动替换 MyBatis SqlSession:
SqlSessionTemplate
作用:
保证同一事务使用同一连接
流程:
五、分布式锁 + 事务顺序问题(重大坑)
很多系统这样写:
@Transactional
public void createOrder(){
RLock lock = redisson.getLock("order");
lock.lock();
orderMapper.insert();
lock.unlock();
}
问题:
锁释放了
事务还没提交
可能出现:
并发数据错误
正确顺序:
示例:
RLock lock = redisson.getLock("order");
lock.lock();
try{
orderService.createOrder(); // 事务方法
}finally{
lock.unlock();
}
六、企业级事务设计规范
总结一套标准架构:
设计原则:
1 事务只放 Service
Controller 不加事务
2 事务范围最小
不要:
HTTP调用
RPC调用
文件操作
3 锁在事务外层
顺序:
Lock
→ Transaction
→ SQL
→ Commit
→ Unlock
4 日志使用独立事务
REQUIRES_NEW
5 禁止在事务中调用远程接口
例如:
RPC
HTTP
MQ
原因:
事务时间过长
数据库锁等待
七、企业级事务架构模板
推荐 Service 模板:
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private LogService logService;
@Transactional
public void createOrder(){
orderMapper.insertOrder();
logService.saveLog();
}
}
日志:
@Service
public class LogService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(){
logMapper.insert();
}
}
常用工具
App Store 截图生成器 、在线图片压缩
乖猫记账,AI智能分类的最佳聊天学生必备记账App。
百度网盘免费加速
总结
企业级 Spring 事务设计核心原则:
1 事务只放 Service
2 默认 REQUIRED
3 日志 REQUIRES_NEW
4 锁在事务外
5 避免远程调用
6 注意 AOP 代理限制
牢记一句话:
Spring 事务不是数据库功能,而是 AOP 代理。
只要理解这一点,80% 的事务问题都能解决。
更多推荐




所有评论(0)