事务的使用
@Transactional 注解可以在类、方法上使用,(方法上使用只能应用到public定义的方法上;类上配置事务,则事务会作用在类中的所有public定义的方法上),方法上使用会覆盖类上定义的声明的事务。
使用事务只要项目引用了spring-boot-starter或者spring-boot-starter-web包即可;这两个依赖包中都已经包含了对于spring-boot-starter-jdbc或者spring-boot-starter-data-jpa的依赖;配置了这两个依赖后,框架会自动分别注入DataSourceTransactionManager和JpaTransactionManager。所以只要配置了这两个依赖后就可以使用事务@Transactional。
注意事项
-
使用事务,遇到检查异常时,开启事务,也无法回滚;
因为spring的默认的事务规则是遇到运行异常(RuntimeException)和程序错误(Error)才会回滚;所以如果遇到类似检查异常时,可以使用事务的属性rollbackFor来指定异常回滚。如@Transactional(rollbackFor=Exception.class)
,如此即可捕捉到异常,进行事务回滚。 -
在代码中手动捕获异常(try…catch),这样也不会事务回滚;
因为这样等同于你捕获了异常,并对异常情况进行了预测和处理,就相当于是一段正常的代码,所以事务也不会捕捉到异常进行事务回滚;解决办法是可以在业务层进行异常捕获,然后将异常抛出到控制层,然后在控制层进行统一处理,在控制层配置事务,控制层可以检测到业务层抛出来的异常然后进行回滚。
事务手动回滚
上面说到,我们在方法上添加了注解@Transactional(rollbackFor=Exception.class)
,但是在方法中我们进行try - catch异常捕获时,有时仍会出现不能回滚的情况,此时我们可以进行手动回滚,我们可以在catch中捕获到异常时进行手动回滚,具体操作如下:
可以在catch中添加如下代码,当代码运行进入了catch时表示我们正常捕获了异常,此时就表示我们的程序出错了,那我们就要进行回滚,但此时,Transactional注解并不会回滚,那就需要我们进行手动回滚。
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
还有第二种方法,就是在我们捕获到异常时,我们可以手动抛出一个RunTimeException异常,这样@Transactional就可以捕捉到异常,然后进行回滚。
事务的属性
propagation:事务的传播行为,默认值为REEQUIRED。
isolation:事务的隔离度,默认值采用DEFAULT。
timeout:事务超时时间,默认值为-1(不超时);设置后(单位秒),则在事务开启后超过该时间事务还未完成,则自动回滚。
read-only:指定事务是否为只读事务,默认值false;此属性主要为忽略哪些不需要事务的方法,如读取数据可设此属性为true。
rollbackFor:用于指定出发事务回滚的异常类型,如果需要指定多个异常类型,中间可用逗号分隔。
noRollbackFor:指定异常不回滚,即遇到指定的异常后事务不会回滚,可配置多个,中间用逗号分隔。
事务的传播
在开启当前事务时,之前已经存在一个事务,则可以指定事务的传播
TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前不存在事务,则创建一个新事物,默认。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:如果当前存在事务,则把当前事务挂起,创建一个新事物。
TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:如果当前存在事务,则把当前事务挂起,以非事务方式运行。
TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。