事务(Transaction)
事务:是数据库中的可以保证多个(至少2个)写操作(增、删、改)要么全部执行成功,要么全部执行失败的机制!
在基于Spring JDBC的项目中,使用@Transactional
注解,即可使得注解的方法是事务性的。
关于@Transactional
注解,可以添加在:
-
接口上
-
等效于在每个抽象方法上添加了此注解
-
-
接口的抽象方法上
-
仅作用于当前方法(重写的方法运行时)
-
-
实现类上
-
等效于在每个重写的接口的方法上添加了此注解
-
-
实现类中重写的接口的方法上
-
仅作用于当前方法
-
提示:此注解可以配置一些参数,如果同时在接口/类、接口的抽象方法/类重写的方法上添加此注解并配置了不同的参数值,则以方法上的配置为准。
注意:Spring JDBC是基于接口的代理模式来实现事务管理的!所以,如果在实现类中的自定义方法上添加@Transactional
注解是错误的做法!仅当对应的方法是在业务接口中已经声明的,使用@Transactional
才是正确的!
关于事务处理过程中的几个概念:
-
开启事务:BEGIN
-
提交事务:COMMIT
-
回滚事务:ROLLBACK
在Spring JDBC的事务管理中,大致是:
开启事务
try {
执行你的业务方法
提交事务
} catch (RuntimeException e) {
回滚事务
}
可以看到,Spring JDBC的事务管理中,默认将根据RuntimeException
进行回滚,可以通过@Transactional
注解的rollbackFor
/ rollbackForClassName
这2个属性中的某1个进行修改,设置为对特定的异常进行回滚,还可以配置noRollbackFor
/ noRollbackForClassName
这2个属性,设置对特定的异常不回滚。
【小结】关于事务:
-
如果某个业务方法涉及超过1次的增、删、改操作,需要保证此业务方法是事务性的;
-
推荐在业务的抽象方法上添加
@Transactional
注解即可保证此业务方法是事务性-
对于初学者,更推荐在业务接口上添加
@Transactional
,则此接口中所有抽象方法都是事务性,可能其中的某些抽象方法并不需要是事务性的,但是,这种做法比较稳妥,能避免遗漏导致的错误
-
-
为了保证事务能够按照预期进行回滚,需要:
-
业务层必须由接口和实现类组成
-
Spring JDBC是基于接口代理模式实现事务管理的,如果没有接口,则无法实现
-
-
所有增、删、改操作完成后,应该及时获取返回结果,并对结果进行判断,如果结果不符合预期,应该抛出异常,且异常应该是
RuntimeException
或其子孙类异常-
Spring JDBC在管理事务时,默认按照
RuntimeException
进行回滚
-
-