1. Spring事务管理基础与@Transactional注解解析
在Spring框架中,事务管理是企业级应用开发的核心功能之一。@Transactional注解作为声明式事务管理的关键实现方式,极大简化了开发人员对事务的控制工作。但正如我们在实际项目中发现的那样,这个看似简单的注解背后隐藏着许多容易踩坑的细节。
Spring事务管理的本质是基于AOP(面向切面编程)实现的。当我们使用@Transactional注解时,Spring会在运行时为被注解的类或方法创建代理对象。这个代理对象负责在方法执行前开启事务,在方法正常执行后提交事务,在方法抛出异常时回滚事务。理解这个基本原理对于避免事务失效至关重要。
1.1 @Transactional注解的核心属性
让我们先全面了解下@Transactional注解的主要属性及其作用:
java复制@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
// 事务传播行为
Propagation propagation() default Propagation.REQUIRED;
// 事务隔离级别
Isolation isolation() default Isolation.DEFAULT;
// 事务超时时间(秒)
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
// 是否只读事务
boolean readOnly() default false;
// 指定哪些异常触发回滚
Class<? extends Throwable>[] rollbackFor() default {};
// 指定哪些异常不触发回滚
Class<? extends Throwable>[] noRollbackFor() default {};
}
每个属性都有其特定的应用场景:
- propagation:控制事务的传播行为,决定当前方法是在现有事务中运行还是新建事务
- isolation:设置事务隔离级别,解决并发事务可能导致的脏读、不可重复读等问题
- timeout:防止长时间运行的事务占用数据库资源
- readOnly:优化只读操作性能
- rollbackFor/noRollbackFor:精确控制哪些异常应该触发回滚
提示:在实际开发中,建议总是显式指定rollbackFor属性,而不是依赖默认行为。这样可以避免因异常类型不匹配导致的事务不回滚问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 事务失效的典型场景与深度解析
2.1 方法内调用导致的事务失效
这是最常见的事务失效场景之一。让我们通过代码示例来深入理解:
java复制@Service
public class PersonServiceImpl implements PersonService {
@Override
public R<String> saveData() throws BusinessException {
save(); // 内部调用
List<String> list = new ArrayList<>();
list.get(0); // 模拟异常
return R.ok();
}
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void save
