zoukankan      html  css  js  c++  java
  • 关于Spring 事务管理传播属性的配置及作用-嵌套事务

    先了解事务的7种传播属性:

    PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 
    PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。 
    PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。 
    PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。 
    PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 
    PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。 
    PROPAGATION_NESTED -- 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 
    前六个策略类似于EJB CMT,第七个(PROPAGATION_NESTED)是Spring所提供的一个特殊变量。 
    它要求事务管理器或者使用JDBC 3.0 Savepoint API提供嵌套事务行为(如Spring的DataSourceTransactionManager)

    问题产生场景:

     1.在 DemoServiceA.java中有方法 demoMethodA().其中嵌套DemoServiceB.java中demoMethodB()。当demoMethodA事务发生rollback时, demoMethodB 事务也可以rollback或是commit。

    如图:

    public class DemoServiceA {
        
        public void demoMethodA() {
            
            demoServiceB.demoMethodB();//Insert对象B 操作
    } }

    常见解决方案: 

    public class DemoServiceA {
        
        /** 
         * 新建事务
         * 事务属性配置为 PROPAGATION_REQUIRED 
         */  
        @Transactional(propagation=Propagation.REQUIRED)
        public void demoMethodA() {
            //操作...
            
            /** 
             * 1.事务属性配置为 PROPAGATION_REQUIRES_NEW ;
             * A. DemoServiceA 事务commit与rollback,与 DemoServiceB无任何关系,DemoServiceB 不属于事务 DemoServiceA的子事务。
             *    PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 
             *    或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 当内部事务开始执行时, 
             *    外部事务将被挂起, 内务事务结束时, 外部事务将继续执行. 
             * B. 可以起到分支执行的效果。service方法虽然嵌套但是事务之间状态相互无影响
             *  
             *  
             *     
             * 2.事务属性配置为 PROPAGATION_NESTED;
             * PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 
             * 潜套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 
             * 我们将回滚到此 savepoint. 潜套事务是外部事务的一部分, 只有外部事务结束后它才会被提交. 
             * 
             */   
            demoServiceB.demoMethodB();//Insert对象B 操作
            //操作...
            
        }
    }

    下面详细介绍7种事务传播属性在示例中的作用:

    1: REQUIRED
    
    加入当前正要执行的事务不在另外一个事务里,那么就起一个新的事务
    
    比如说,DemoServiceB.demoMethodB的事务级别定义为REQUIRED, 那么由于执行DemoServiceA.demoMethodA的时候,
    
    DemoServiceA.demoMethodA已经起了事务,这时调用DemoServiceB.demoMethodB,DemoServiceB.demoMethodB看到自己已经运行在DemoServiceA.demoMethodA
    
    的事务内部,就不再起新的事务。而假如DemoServiceA.demoMethodA运行的时候发现自己没有在事务中,他就会为自己分配一个事务。
    
    这样,在DemoServiceA.demoMethodA或者在DemoServiceB.demoMethodB内的任何地方出现异常,事务都会被回滚。即使DemoServiceB.demoMethodB的事务已经被
    
    提交,但是DemoServiceA.demoMethodA在接下来fail要回滚,DemoServiceB.demoMethodB也要回滚
    
    2: SUPPORTS
    
    如果当前在事务中,即以事务的形式运行,如果当前不再一个事务中,那么就以非事务的形式运行
    
    3: MANDATORY
    
    必须在一个事务中运行。也就是说,他只能被一个父事务调用。否则,他就要抛出异常
    
    4: REQUIRES_NEW
    
    这个就比较绕口了。 比如我们设计DemoServiceA.demoMethodA的事务级别为REQUIRED,DemoServiceB.demoMethodB的事务级别为REQUIRES_NEW,
    
    那么当执行到DemoServiceB.demoMethodB的时候,DemoServiceA.demoMethodA所在的事务就会挂起,DemoServiceB.demoMethodB会起一个新的事务,等待DemoServiceB.demoMethodB的事务完成以后,
    
    他才继续执行。他与REQUIRED 的事务区别在于事务的回滚程度了。因为DemoServiceB.demoMethodB是新起一个事务,那么就是存在
    
    两个不同的事务。如果DemoServiceB.demoMethodB已经提交,那么DemoServiceA.demoMethodA失败回滚,DemoServiceB.demoMethodB是不会回滚的。如果DemoServiceB.demoMethodB失败回滚,
    
    如果他抛出的异常被DemoServiceA.demoMethodA捕获,DemoServiceA.demoMethodA事务仍然可能提交。
    
    5: NOT_SUPPORTED
    
    当前不支持事务。比如DemoServiceA.demoMethodA的事务级别是REQUIRED ,而DemoServiceB.demoMethodB的事务级别是NOT_SUPPORTED ,
    
    那么当执行到DemoServiceB.demoMethodB时,DemoServiceA.demoMethodA的事务挂起,而他以非事务的状态运行完,再继续DemoServiceA.demoMethodA的事务。
    
    6: NEVER
    
    不能在事务中运行。假设DemoServiceA.demoMethodA的事务级别是REQUIRED, 而DemoServiceB.demoMethodB的事务级别是NEVER ,
    
    那么DemoServiceB.demoMethodB就要抛出异常了。
    
    7: NESTED
    
    理解Nested的关键是savepoint。他与REQUIRES_NEW的区别是,REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,
    
    而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。
  • 相关阅读:
    shell cut
    查询表名
    RandomAccessFile
    eclipse 背景颜色
    JAVA 获取分行符
    date time insert
    shell date time
    python
    gdg shell
    shell入门之变量测试
  • 原文地址:https://www.cnblogs.com/cnmenglang/p/6410848.html
Copyright © 2011-2022 走看看