基于Spring JDBC的事务处理

事务(Transaction):在数据库中,可以保持一系列的数据操作要么全部执行成功,要么全部执行失败的机制!

假设存在以下信息:

账户 余额
阿三 1000
王五 8000

如果存在任务“王五向阿三转账5000元”,需要执行的SQL语句大致是:

update 账户信息表 set 余额=余额-5000 where 账户='王五';
update 账户信息表 set 余额=余额+5000 where 账户='阿三';
复制代码

如果出现某种意外,导致以上第1条SQL语句成功执行了,第2条却无法执行或执行失败,就会出现数据安全问题(当然,把以上2条SQL语句的执行顺序对调后,出现以上状态也是不安全的)。

在以上这种“转账”的任务中,如果2条SQL语句都执行成功,就是预期的效果,但是,即使是2条SQL语句都执行失败了,数据安全也不会受到影响,也属于是可以接受的。

在基于Spring JDBC的编程中,只需要为业务方法加上@Transactional注解,就可以使得该业务方法中的多条数据操作是有事务的保障的,这多条数据操作要么全部成功,要么全部失败,不会出现成功一半且失败一半的问题!

框架在处理“事务”时,其大致的执行方式是:

try {
	开启事务(BEGIN)
	执行一系列的数据操作
	提交事务(COMMIT)
} catch (RuntimeException e) {
	回滚事务(ROLLBACK)
}
复制代码

所以,在基于Spring JDBC的编程中,需要注意:

  • 如果某个业务涉及2次或2次以上的增删改(例如2次UPDATE操作,或1次INSERT与1次DELETE,或其它)操作,必须在业务方法的声明之前添加@Transactional注解,以使得该业务的执行过程中是有事务的保障的;
  • 在调用持久层的增删改操作时,必须及时获取返回的受影响行数,并判断受影响行数是否是预期值,如果不是,必须抛出RuntimeException或其子孙类异常!

另外,@Transactional注解还可以添加在业务类的声明之前,则当前业务类中所有业务方法都是有事务保障的,但是,通常没有这个必要性,所以,并不推荐这样使用!

课后,可自行了解:事务的ACID特性,事务的传播,事务的隔离。