一、定义
在使用事务之前,我们要理解下事务概念: 什么是事务呢?事务是并发控制的单位,是用户定义的一个操作序列。有四个特性:
1、原子性(Atomicity): 事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。
2、一致性(Consistency): 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
3、隔离性(Isolation): 一个事务的执行不能被其他事务干扰。
4、持续性/永久性(Durability): 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。
事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态。事务管理是Spring框架中最为常用的功能之一,我们在使用Spring Boot开发应用时,大部分情况下也都需要使用事务。
二、Spring事务的五大属性
1、 事务隔离级别
隔离级别是指若干个并发事务之间的隔离程度。Spring Boot的隔离级别被封装在枚举类Isolation,枚举值取自接口TransactionDefinition 定义。
本人一般使用默认值为:ISOLATION_DEFAULT:默认值,使用后端数据库默认的隔离级别
2、事务传播规则
事务传播行为(propagation behavior)用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时候,事务如何传播。
传播行为定义了事务范围,何时触发事务,是否暂停现有事务,或者在调用方法是如果没有事务则失败等等。
Spring Boot的事务传播行为常量被封装在枚举类Propagation,枚举值取自接口TransactionDefinition。
本人一般使用:
(1)REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;
(2)REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;
接下来说明一下其中的区别:
public class a { @Transactional public void useB() { try { b.test(); } catch (RuntimeException e) { System.err.println(e.getMessage()); } } }
public class b { @Transactional public static void test() { throw new RuntimeException("b throw exception"); } }
此时运行程序就会报错,原因如下:
b此时和a是使用的一个事务,当b抛出异常时,事务想要将异常rollback,而a又使用try捕获的异常进行处理,此时出现冲突,报错
进行b代码的修改为:
public class b { @Transactional(propagation = Propagation.REQUIRES_NEW) public static void test() { throw new RuntimeException("b throw exception"); } }
3、事务超时
@Transactional(timeout = 1) // 设置多长时间不完成,事务回滚
4、事务只读属性
@Transactional(readOnly = true) // 设置事务为只读
5、事务的回滚
/** * * @version: 1.1.0 * @Description: 事物的回滚测试 * @author: wsq * @date: 2020年6月23日下午9:39:15 */ @RestController public class TestController { @GetMapping("/test") // 设置异常类的回滚 // @Transactional(rollbackFor = {RuntimeException.class}) //设置回滚异常类 // @Transactional(noRollbackFor = {RuntimeException.class}) // 设置不回滚异常类 // @Transactional(rollbackForClassName = {"RuntimeException"}) //设置回滚异常名称 // @Transactional(noRollbackForClassName = {"RuntimeException"}) //设置不回滚异常名称 // @Transactional(timeout = 1) // 设置多长时间不完成,事务回滚 @Transactional(propagation = Propagation.REQUIRED) public void test() { // 手动回滚 try { } catch (Exception e) { // TODO: handle exception TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); } // 自定义节点回滚 Object savePoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint(); TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savePoint); } }