本章,我们将深入探讨Spring事务管理,为你揭秘@Transactional注解底层工作原理。
JPA和事务管理
首先,我们要知道,JPA本身不提供任何声明式事务管理。当我们在任意依赖注入容器外使用JPA时,需要由开发人员以编程方式来处理事务。
UserTransaction utx = entityManager.getTransaction();
try {
utx.begin();
businessLogic();
utx.commit();
} catch(Exception ex) {
utx.rollback();
throw ex;
}
这种管理事务的方式使得代码中的事务范围非常清晰,但它有几个明显不足:
- 代码重复且容易出错
- 任意一个微小的错误都都可能会产生很大的影响
- 错误很难调试和重现
- 降低了代码的可读性
- 如果此方法调用另一个事务方法如何处理事务?
使用Spring @Transactional注解
如果我们使用@Transactional注解,那么上面的代码就可以简化为:
@Transactional
public void businessLogic() {
... use entity manager inside a transaction ...
}
这样以来,通过@Transactional注解使得代码更方便和可读,这也是目前Spring中事务处理的推荐做法。
通过使用 @Transactional,许多事务相关的都可以被自动处理,例如:事务传播等等。例如,如果businessLogic()方法调用另一个事务方法 ,该方法将根据事务传播配置确定是否加入当前正在进行的事务。
然而,万事皆有两面性,@Transactional的强大机制为我们的事务管理提供了便利,然而正是这种强大机制隐藏了内部实现细节,进而使得当问题发生时,我们无法很好的去跟踪调试。