@Transactional注解默认会回滚运行时异常及其子类,其它范围之外的异常不会回滚(如果也想要回滚,在方法或者类加上@Transactional(rollbackFor = Exception.class) 即可)
运行时异常RuntimeException,其子类如NullpointerException、IndexOutOfBoundsException、CalssCaseException等。非RuntimeException如IOException、ClassNotFoundException(这类异常不会触发回滚,除非用rollbackFor指定某类异常或全部异常的父类Exception)
@Transactional 注解只能应用到 public 方法或者类上才有效
@Transactional 注解的属性
1、事务的传播类型(propagation 属性默认值为 Propagation.REQUIRED)
什么叫事务传播?即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
可以配置的传播类型有
1.PROPAGATION_REQUIRED:表示当前方法必须在事务中执行,如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入该事务(这是最常见的选择)
2.PROPAGATION_SUPPORTS:如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行
3.PROPAGATION_MANDATORY:如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常
4.PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事务
5.PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。例如 方法A支持事务,方法B不支持事务,方法A调用方法B,在方法A开始运行时,系统为它建立Transaction,方法A中对于数据库的处理操作,会在该Transaction的控制之下。这时,方法A调用方法B,方法A打开的 Transaction将挂起,方法B中任何数据库操作,都不在该Transaction的管理之下。当方法B返回,方法A继续运行,之前的Transaction恢复,后面的数据库操作继续在该Transaction的控制之下提交或回滚。
6.PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常
7.PROPAGATION_NESTED:如果存在活动事务,则在嵌套事务中运行。如果没有活动事务,则与PROPAGATION_REQUIRED相同
2、事务隔离级别(默认值为 Isolation.DEFAULT)
并发问题可归纳为以下几类:
A.丢失更新:撤销一个事务时,把其他事务已提交的更新数据覆盖(A和B事务并发执行,A事务执行更新后,提交;B事务在A事务更新后,B事务结束前也做了对该行数据的更新操作,然后回滚,则两次更新操作都丢失了)。
B.脏读:一个事务读到另一个事务未提交的更新数据(A和B事务并发执行,B事务执行更新后,A事务查询B事务没有提交的数据,B事务回滚,则A事务得到的数据不是数据库中的真实数据。也就是脏数据,即和数据库中不一致的数据)。
C.不可重复读:一个事务读到另一个事务已提交的更新数据(A和B事务并发执行,A事务查询数据,然后B事务更新该数据,A再次查询该数据时,发现该数据变化了)。
D. 覆盖更新:这是不可重复读中的特例,一个事务覆盖另一个事务已提交的更新数据(即A事务更新数据,然后B事务更新该数据,A事务查询发现自己更新的数据变了)。
E.虚读(幻读):一个事务读到另一个事务已提交的新插入的数据(A和B事务并发执行,A事务查询数据,B事务插入或者删除数据,A事务再次查询发现结果集中有以前没有的数据或者以前有的数据消失了)。
数据库系统提供了四种事务隔离级别供用户选择:
A.Serializable(串行化):一个事务在执行过程中完全看不到其他事务对数据库所做的更新(事务执行的时候不允许别的事务并发执行。事务串行化执行,事务只能一个接着一个地执行,而不能并发执行。)。
B.Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,但是不能看到其他其他事务对已有记录的更新。MySQL默认的隔离级别。
C.Read Commited(读已提交数据):一个事务在执行过程中可以看到其他事务已经提交的新插入的记录,而且能看到其他事务已经提交的对已有记录的更新。Oracle默认的隔离级别。
D.Read Uncommitted(读未提交数据):一个事务在执行过程中可以看到其他事务没有提交的新插入的记录,而且能看到其他事务没有提交的对已有记录的更新。
丢失更新 | 脏读 | 不可重复读 | 覆盖更新 | 幻像读 | |
读未提交 | Y | Y | Y | Y | Y |
读已提交 | N | N | Y | Y | Y |
可重复读 | N | N | N | N | Y |
串行化 | N | N | N | N | N |