Spring事务
- 一、什么是事务、事务的特性、事务的隔离级别
- 二、Spring中事务实现
- 编程式事务:手动写代码操作事务
- 声明式事务:使用注解自动开启和提交事务
- 三、Spring事务隔离级别及设置方法
- 四、Spring的事务传播机制
- Spring事务失效的情况
- @Transactional注解
- 参数说明:
- 说明
一、什么是事务、事务的特性、事务的隔离级别
事务就是逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败。
事务具有四大特性(ACID),原子性(Atomomicity),一致性(Consistency),持久性(Isolation),隔离性(Durability)。不同的隔离级别总共可能产生三种问题脏读,不可重复度,幻读。
MySQL事务的隔离级别有四种read uncommited,read commited,repeatable read,serializable,MySQL默认是可重复读。读未提交三种问题都可能产生,读已提交可以解决脏读问题,但是解决不了不可重复读和幻读问题,可重复读可以解决前两种问题,串行化可以解决这三种问题。
二、Spring中事务实现
编程式事务:手动写代码操作事务
以向数据表删除记录为例
- 拿到JDBC事务管理器( DataSourceTransactionManager)对象
- 拿到事务定义(TransactionDefinition)对象
- 开启事务
- 插入数据库
- 提交事务/回滚事务
@RestController
@RequestMapping("/user0")
public class UserController0 {@Autowiredprivate UserService userService;//1.创建JDBC事务管理器和事务定义对象@Autowiredprivate DataSourceTransactionManager transactionManager;@Autowiredprivate TransactionDefinition transactionDefinition;@RequestMapping("/del")public int del(Integer id) {if(id != null && id > 0) {//2.开启事务TransactionStatus transactionStatus =transactionManager.getTransaction(transactionDefinition);//3.删除用户业务操作int result = userService.del(id);System.out.println("删除了: " + result);// 4.提交事务/回滚事务
// transactionManager.commit(transactionStatus); //提交事务transactionManager.rollback(transactionStatus); //回滚事务}return 0;}
}
@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public int del(Integer id){return userMapper.del(id);}
}
@Mapper
public interface UserMapper {int del(@Param("id")Integer id);
}
<delete id="del">delete from userinfo where id=#{id}
</delete>
声明式事务:使用注解自动开启和提交事务
在方法/类上加@Transactinonal注解。
进入方法自动开启事务,执行完毕自动提交,发生异常自动回滚事务:
成功的情况:
@RestController
@RequestMapping("/user0")
public class UserController0 {@Autowiredprivate UserService userService;@Transactional@RequestMapping("/del2")public int del2(Integer id) {if(id == null || id <= 0) {return 0;}return userService.del(id);}
}
对应的mapper和xml配置不用变,还是调用对象的service里的方法。
报异常并回滚事务的情况:
这里人为加一个算数异常:
@Transactional
@RequestMapping("/del3")
public int del3(Integer id) {if(id == null || id <= 0) {return 0;}int result=0;result=userService.del(id);int num=10/0;System.out.println(result);return result;
}
三、Spring事务隔离级别及设置方法
Spring事务默认级别就是对应连接数据的默认隔离级别
和MySQL的隔离级别含义基本一模一样。
通过Transactional的isolation属性设置:
四、Spring的事务传播机制
多个事务进行嵌套调用的时,事务的执行行为叫做事务的传播机制。事务传播机制保证每个事务在多个调用方法间可控。
事务的传播机制一共分为三大类:支持当前事务,不支持当前事务和嵌套事务。
- 支持当前事务:以REQUIRED为例,一旦发生异常调用链上的所有事务全部回滚
- 不支持当前:以REQUIRED_NEW为例,
- 嵌套事务:嵌套事务可以回滚部分事务。(外部/主事务和内部/子事务)
- 主事务提交成功,子事务也会被提交
- 主事务回滚,子事务无论是否成功,一定回滚
Spring事务失效的情况
1.异常捕获处理
去掉try catch包裹
在之前的代码上边加try catch处理,再运行可以发现数据库的记录被删除,报错,事务失效
因为事务通知只有自己捕捉到了对应代码抛出的异常,才能进行回滚操作,这里如果自己处理了,事务没办法感知到。
2.非public修饰的方法
将方法设置成Public类型的
3.抛出受查异常
原因:spring默认只能回滚非受查异常。
解决办法:将@Transactional的rollbackFor属性设置为Exception.class
@Transactional注解
@Transactional使用方法:修饰类对类中所有public方法都生效,修饰方法对public方法生效。
参数说明:
参数 | 作用 |
---|---|
value | 当配置了多个事务管理器时,可使用该属性指定选择哪个事务管理器 |
transactionManager | 当配置多个事务管理器,可使用该使用指定选择哪个事务管理器 |
propagation | 事务的传播机制,默认值为Propagation.REQUIRED |
isolation | 事务的隔离级别,默认值为Isolation.DEFAULT |
timeout | 事务的超时时间,默认值为-1,如果超过该事件限制但事务还没完成,则自动回滚事务 |
readOnly | 指定事务是否为只读事务,默认值为false |
rollbackFor | 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型 |
rollbackForClassName | 用于指定能够触发事务回滚的异常类型,可以指定多个异常类型(字符串类型) |
noRollbackFor | 不回滚抛出异常 |
noRollbackForClassName | 不回滚抛出异常(字符串类型) |
说明
实际开发中,绝大部分时候会使用声明式事务,毕竟只需要加一个注解就可以实现想要的功能。