在企业级 Spring Boot 项目中,@Transactional 是最常用但最容易被误用的注解之一。
很多系统上线后才发现:
本文总结一套 企业级事务设计规范,包含:
1️⃣ @Transactional 8 大常见失效场景
2️⃣ 事务传播最佳实践
3️⃣ MyBatis + Spring 事务机制原理
4️⃣ 分布式锁 + 事务顺序问题

Spring 事务本质是 AOP + 数据源事务管理器。

执行流程:
调用 Service 方法
↓
Spring AOP 拦截
↓
开启事务
↓
执行 SQL
↓
成功 → commit
异常 → rollback这是生产事故最多的 8 种情况。
事务依赖 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()Spring 默认只代理 public 方法。
错误示例:
@Transactional
private void saveUser(){
}正确:
@Transactional
public void saveUser(){
}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();Spring 默认只回滚:
RuntimeException
Error不会回滚:
CheckedException错误示例:
@Transactional
public void test() throws Exception {
throw new Exception("error");
}解决:
@Transactional(rollbackFor = Exception.class)很多人这样写:
@RestController
public class OrderController {
@Transactional
@PostMapping("/create")
public void create(){
orderService.create();
}
}问题:
正确:

事务放在:
@Service
public class OrderService {
@Transactional
public void create(){
orderMapper.insert();
}
}错误示例:
UserService userService = new UserService();
userService.save();Spring AOP 无法代理:
事务失效必须:
@Autowired
UserService userService;@Transactional
public void createOrder(){
new Thread(() -> {
orderMapper.insert();
}).start();
}事务只在当前线程有效。

Spring 默认 JDK/CGLIB 代理
final 方法无法被代理:
@Transactional
public final void save(){
}事务失效。
事务传播用于:
事务嵌套
微服务调用
日志记录
补偿操作Spring 支持 7 种传播行为。
传播级别 | 说明 |
|---|---|
REQUIRED | 默认,加入当前事务 |
REQUIRES_NEW | 新事务 |
SUPPORTS | 有事务就加入 |
NOT_SUPPORTED | 不使用事务 |
MANDATORY | 必须有事务 |
NEVER | 不能有事务 |
NESTED | 嵌套事务 |
@Transactional
public void createOrder(){
}保证日志一定提交。
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void saveLog(){
}架构:

即使主事务回滚:
日志仍然存在REQUIRES_NEW适用于:
操作日志
审计日志
系统日志很多人误以为:
MyBatis 自动管理事务实际上:
Spring 管理事务
MyBatis 只执行 SQL架构:

关键组件:
DataSourceTransactionManager
SqlSessionTemplateSpring 会自动替换 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();
}总结一套标准架构:

设计原则:
Controller 不加事务不要:
HTTP调用
RPC调用
文件操作顺序:
Lock
→ Transaction
→ SQL
→ Commit
→ UnlockREQUIRES_NEW例如:
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% 的事务问题都能解决。