zoukankan      html  css  js  c++  java
  • (入门SpringBoot)SpringBoot项目事务(三)

         Spring声明式事务的使用:@Transactional进行标注,可以使用在类和方法上。当标注在类上,类下面所有公共非静态的方法都将启用事务功能。接下来,运行事务注解标注的方法,Spring的事务拦截器就会同时使用事务管理的方法开启事务,然后将代码织入Spring数据库事务的流程中,如果发生异常,就会回滚,如果不发生异常,那么就会提交事务。

      

    spring事务流程图(自己瞎画的):

    1.@Transactional源码分析:
       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.@Transactional自调用失效的问题:
       类自身的调用是不会产生AOP的,解决方法可以使用一个Service去调用另一个Service,这样就是代理对象的调用,Spring才会将你的代码,放入AOP.
  • 相关阅读:
    element-ui upload 上传图片之前压缩
    字符串截取substring放法传参不同返回不同
    vue中对于图片是否正常加载的思考
    前端图片合成并下载
    vue中图相对路径引用本地图片
    js计算精度
    vue-cli定义全局过滤器
    js加减乘除运算丢失精度 前端计算金额带小数点精度丢失问题
    鼠标样式大全
    js两小时倒计时,剩余时间倒计时,倒计时
  • 原文地址:https://www.cnblogs.com/historylyt/p/10924977.html
Copyright © 2011-2022 走看看