基于Spring JDBC的事务管理
事务(Transaction):有时会简写为tx,是数据库中一种可以保障多个写操作(增/删/改)要么全部成功,要么全部失败的机制!
假设存在用户之间的转账行为,需要执行的SQL可能是:
update 账户余额表 set 余额=余额-1000 where 账户='传奇';
update 账户余额表 set 余额=余额+1000 where 账户='国斌';
以上2条SQL语句,无论先执行哪一条,如果前一条执行成功,后一条执行失败,是不可接受的。
有了事务以后,可以保障以上2条SQL语句要么全部成功,则转账成功,要么全部失败,转账失败,且2个账户的余额没有发生任何变化。
在Spring Boot项目中,添加了数据库编写的依赖项后,就会包含spring-jdbc的依赖项,例如:
在Spring JDBC的事务管理中,只需要在业务方法上添加@Transactional注解,就可以使得此方法是“事务性”的,例如:
以上使用的@Transactional注解可以添加在:
- 添加在类的方法上
- 作用于当前方法
- 添加在类上
- 作用于当前类中所有重写的接口中定义的方法
- 添加在接口的抽象方法上
- 作用于实现了此接口的类中重写的方法
- 添加在接口上
- 作用于实现了此接口的类中的所有的重写的方法
**注意:**Spring JDBC在实现事务管理时,底层实现是基于接口代理的,所以,在实现类的类中的自定义方法,不可以添加@Transactional注解!
Spring JDBC在处理事务管理时,大致的处理流程如下:
try {
开启事务(关闭自动提交):BEGIN
执行业务方法
提交事务(保存):COMMIT
} catch (RuntimeException e) {
回滚事务(关闭时不保存):ROLLBACK
} finally {
(开启自动提交)
}
Spring JDBC在处理事务时,默认根据RuntimeException执行回滚,在@Transactional注解中,可以配置rollbackFor或rollbackForClassName属性,指定根据某种RuntimeException执行回滚,还可以配置noRollbackFor或noRollbackForClassName属性,指定不执行回滚的异常类型。
小结:
- 如果某个业务方法涉及多次写操作,必须保证它是事务性的
- 应该在需要保障事务性的抽象方法上添加
@Transactional注解- 在学习阶段,或不需要过度关注执行效率的项目开发中,可以把
@Transactional直接添加在接口上
- 在学习阶段,或不需要过度关注执行效率的项目开发中,可以把
- 在编写业务代码时,如果视为“操作失败”(例如增、删、改后得到的“受影响的行数”不符合预期),应该及时抛出
RuntimeException或其子孙类异常,使得事务回滚
其它:
- 你应该抽空学习事务的ACID特性、事务的传播、事务的隔离。