目录
事务定义
为什么要用事务
Spring中事务的实现
编程式事务
声明式事务
@Transactional
@Transactional的作用范围
@Transactional的参数说明
Spring事务的隔离级别
@Transactional的注意事项
Spring里事务失效的场景
Spring事务的传播机制
嵌套事务和加入事务的区别
将一组操作封装成一个执行单元(封装到一起),要么全部成功,要么全部失败.
比如转账分为两个操作,A账户-100,B账户+100,如果第一步成功了,第二部失败了,那么A账户就会平白无故的减去100,使用事务就可以解决这个问题,要么一起成功,失败就回滚.
Spring中的事务操作分为两类:编程式事务(手动写代码操作事务)和声明式事务(利用注解自动开启和提交事务).
spring编程式事务有3个重要步骤:开启事务(获取事务),提交事务,回滚事务.
SpringBoot内置了两个对象,DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或
@RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; //编程式事务 //操作事务的时候,需要通过事务管理器 @Autowired private DataSourceTransactionManager transactionManager; //事务的属性,要求通过事务管理器transactionManager得到事务transactionStatus的时候 // 需要传递事务的属性transactionDefinition @Autowired private TransactionDefinition transactionDefinition; @RequestMapping("/del") public int del(Integer id){ if (id!=null && id>0){ //1.开启事务 TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition); //业务操作,删除用户 int result = userService.del(id); System.out.println("删除: " + result); //2.提交事务或者回滚事务 //transactionManager.commit(transactionStatus); //提交事务 transactionManager.rollback(transactionStatus); //回滚事务 return result; } return 0; } }
声明式事务的实现很简单,只需要在需要开启事务的方法上添加@Transactional注解即可,无需手动开启事务和提交事务,进入方法时自动开启事务,方法执行完会自动提交事务,如果中途发生了没有处理的异常就会自动回滚事务.
@RestController @RequestMapping("/user2") public class UserController2 { @Autowired private UserService userService; @RequestMapping("/del2") @Transactional public int del(Integer id){ if (id==null && id<=0){ return 0; } return userService.del(id); } }
@Transactional可以用来修饰方法或者类.
修饰方法的时候,需要注意的是,只能应用到public方法上,否则不生效.
修饰类的时候,表明该注解对该类中所有的public方法都生效.
timeout默认是-1,表示没有超时时间.
只读事务比普通事务的执行效率要高,如果只有读操作,可以把readOnly设置成true.
默认就是以连接的数据库的隔离级别为准.
@Transactional在异常被捕获的情况下(出现了异常并添加了try-catch语句),不进行事务的自动回滚,导致业务执行出错.
解决方案:
1.将异常抛出去,让框架感知到异常,如果框架感知到异常之后,它也会自动回滚事务.
2. 通过代码的方式手动回滚事务
拿到当前的事务并进行回滚.
Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递的。
为什么需要事务传播机制
事务隔离级别保证多个并发的事务执行是可控性的,而事务传播机制是保证一个事务在多个调用方法间的可控性.
整个事务如果全部执行成功,二者的结果都是一样的.如果事务执行到一半失败了,那么加入事务是整个事务会全部回滚;而嵌套事务实现的是局部回滚,不会影响上一个方法的执行结果.嵌套事务只所以能够实现部分事务的回滚,是因为事务中有⼀个保存点(savepoint)的概念,嵌套事务进⼊之后相当于新建了⼀个保存点,⽽回滚时只回滚到当前保存点,因此之前的事务是不受影响的.