1、@Transactional
@Transactional注解是声明式事务管理方式,通过注解即可管理事务,无需手动编写事务模板代码,适用于简单的事务操作和需要快速实现事务管理的场景。
优点
- 代码简洁:通过注解即可管理事务,无需手动编写事务模板代码,减少侵入性。
- 集中管理:事务配置(传播行为、隔离级别、回滚规则等)集中到注解中,方便维护。
- AOP支持:基于Spring AOP实现,天然支持事务的传播行为和嵌套事务。
- 统一异常回滚:默认对
RuntimeException
和Error
回滚,可通过rollbackFor
/noRollbackFor
配置。
缺点
- 隐式控制:事务边界由代理机制隐式管理,调试和理解复杂场景时可能不够直观。
- 自调用问题:同类内的方法调用(如
this.method()
)会绕过代理,导致@Transactional
失效。 - 异常处理敏感:默认只回滚非受检异常(如
RuntimeException
),需显式配置受检异常(如SQLException
)。 - 粒度限制:事务只能作用于方法级别,无法在代码块级别更细粒度控制。
使用
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional
public void createUser(User user) {
userRepository.save(user);
// 模拟异常
if (true) {
throw new RuntimeException("模拟异常");
}
}
}
2、TransactionTemplate
TransactionTemplate是Spring提供的编程式事务管理工具,通过代码显式控制事务的开启、提交和回滚,适用于需要动态或复杂事务逻辑的场景。
优点
- 显式控制:事务代码完全由开发者手动编写,事务边界清晰可见。
- 灵活控制:可以在代码块级别控制事务(例如:在循环中部分提交事务)。
- 精细异常处理:直接在代码中处理异常,可灵活决定回滚或提交。
- 避免代理问题:不受Spring AOP代理机制限制(如自调用问题)。
缺点
- 代码冗余:需要显式编写事务模板代码,侵入性较高。
- 维护成本:事务逻辑分散在代码中,可能增加维护难度。
- 事务传播配置复杂:需要手动处理事务传播行为(例如嵌套事务)。
使用
@Service
@Slf4j
public class TransactionTemplateDemo {
@Resource
private UserRepository userRepository;
@Resource
private TransactionTemplate transactionTemplate;
// 1、execute(TransactionCallback<T> action)
// 功能:执行包含事务的代码块,支持返回值。
public void demo() {
transactionTemplate.execute((status) -> {
try {
//执行方法
save();
//制造异常
int i = 1 / 0;
return true;
} catch (Exception e) {
log.error("保存失败", e);
//回滚
status.setRollbackOnly();
log.info("数据回滚~");
return false;
}
});
}
// 2、executeWithoutResult(Consumer<TransactionStatus> action)
// 功能:执行包含事务的代码块,支持返回值。
public void demo2() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
//执行方法
save();
save2();
} catch (Exception e) {
log.error("保存失败", e);
//回滚
transactionStatus.setRollbackOnly();
log.info("数据回滚~");
}
}
});
}
public void save() {
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
user.setRegdate(new Date());
userRepository.save(user);
log.info("保存成功");
}
public void save2() {
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
userRepository.save(user);
log.info("保存成功");
}
}
3、注意事项
- 异常处理:
@Transactional
默认回滚RuntimeException
和Error
,需通过rollbackFor
配置其他异常。TransactionTemplate
需在代码中显式捕获异常并调用status.setRollbackOnly()
。
- 事务传播行为:
@Transactional
可通过propagation
属性配置(如Propagation.REQUIRES_NEW
)。TransactionTemplate
需通过TransactionDefinition
手动配置。
- 性能:两者性能差异可忽略,优先考虑代码可维护性。