Spring声明式事务的使用:由@Transactional进行标注,可以使用在类和方法上。当标注在类上,类下面所有公共非静态的方法都将启用事务功能。接下来,运行事务注解标注的方法,Spring的事务拦截器就会同时使用事务管理的方法开启事务,然后将代码织入Spring数据库事务的流程中,如果发生异常,就会回滚,如果不发生异常,那么就会提交事务。
spring事务流程图(自己瞎画的):
1[email protected]源码分析: timeout是事务可以存在的时间戳.(单位为秒) Value和transactionManager属性是配置的一个Spring事务管理器. readOnly属性定义事务是否只读. rollbackFor,rollbackForClassName,noRollbackFor和noRollbackForClassName都是指定异常.发生什么异常回滚事务. propagation传播行为. isolation隔离级别 2.隔离级别: 关于隔离级别,先说一下数据库事务的4个基本特征,也就是ACID,也算是老话长谈了, 原子性:(事务的操作是一个整体,要么全部成功,要么全部失败,不会出现部分成功,部分失败.), 一致性:(事务在完成的时候,必须所有的数据都保持一致的状态.), 隔离性:(不同事务操作的数据,互相不影响), 持久性:(事务执行过后,数据会存储到数据库中) 隔离级别解决的事情,举个例子说明: 2.1.一个商品初始化为2,事务一扣减库存1,库存为1,事务2扣减库存,读取到事务1为提交的库存数据,扣减库存1,提交事务,库存保存为0,事务一回滚事务,库存结果为0,结果错误. 未提交读(read uncommitted)最低的隔离级别,允许一个事务度去另一个事务没有提交的数据. 2.2.读写提交(read committed)隔离级别,是指定一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据.有效的解决了2.1.脏读的问题. 但是仍旧会出现下列问题: 不可重读场景:商品库存初始化为1,事务一读取库存1,扣减库存,未提交,事务2读取库存1,认为可以扣减,此时事务一提交,库存变为0,事务2扣减库存失败,库存为0,无法扣减. 可重复读:就是克服读写提交中出现的不可重复读的情况,因为在读写提交的时候,确实会出现一些值的变化. 简单点说,就是库存已经被事务一先读取,所以这个时候数据库就阻塞它的读取,直到事务一提交,事务2才能读取库存的值. 幻读:举个例子,事务一读取库存50件货,商品库存初始化为100,现在已经销售了50,剩余50,事务2读取交易记录50,事务一扣减库存,插入交易记录,提交事务,库存49件,交易记录51笔,事务2打印交易记录51笔,这里与查询不一致,在事务2看来有1笔是虚幻的,与之前查询不一致. 2.3.串行化(serializable),数据库隔离最高级别,所有sql按顺序执行. 提示:可以在代码中配置隔离级别. # -1 数据库默认隔离级别, #1 未提交读 #2 读写提交 #4 可重复读 #8 串行化 # tomcat 数据源默认隔离级别: Spring.datasource.tomcat.default-transaction-isolation=2 #dbcp2数据库连接池默认隔离级别 Spring.datasource.dbcp2.default-transaction-isolation=2 3.传播行为: 在Spring中当一个方法调用另外一个方法时,可以让事务采取不同的策略工作。 3.1.传播行为的定义: REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED):需要事务,它是默认的传播行为,如果当前存在事务,就用当前的事务,否则新建一个事务运行子方法. SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS):支持事务,如果当前存在事务,就用当前事务,如果不存在,就继续采用无事务的方式运行子方法. MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY):必须使用事务,如果当前没有事务,就会抛出异常,如果存在当前事务,那么就使用当前事务. REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW):无论当前事务是否存在,都会创建新的事务执行方法,这样新的事务就可以拥有新的锁和隔离级别的特性,与当前事务互相独立. NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED)不支持事务,当前存在事务,将挂起事务,运行方法. NEVER(TransactionDefinition.PROPAGATION_NEVER)不支持事务,如果当前方法有事务,就抛出异常,否则继续使用无事务机制运行. NESTED(TransactionDefinition.PROPAGATION_NESTED)在当前方法调用子方法时候,如果子方法发生异常,只回滚子方法执行过的sql,而不会滚当前方法的事务. 3.2[email protected]自调用失效的问题: 类自身的调用是不会产生AOP的,解决方法可以使用一个Service去调用另一个Service,这样就是代理对象的调用,Spring才会将你的代码,放入AOP.
原文地址:https://www.cnblogs.com/historylyt/p/10924977.html
时间: 2024-11-14 11:57:15