• 事务


    两种配置事务的方式

    1.非注解式事务配置

    2. 注解式事务配置
     
    非注解式事务配置
    <!-- 基本数据源配置  -->
    <bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="maxWait" value="3000"/>
    <property name="validationQuery" value="SELECT 1"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testWhileIdle" value="true"/>
    <property name="initialSize" value="100"/>
    <property name="maxActive" value="200"/>
    <property name="minIdle" value="10"/>
    <property name="maxIdle" value="50"/>
    <property name="removeAbandoned" value="true"/>
    <property name="removeAbandonedTimeout" value="30"/>
    <property name="timeBetweenEvictionRunsMillis" value="30000"/>
    <property name="driverClassName" value="${feima.jdbc.driver}"/>
    </bean>

    <bean id="feimaDataSource" parent="parentDataSource">
    <property name="url" value="${feima.wr.jdbc.url}"/>
    <property name="username" value="${feima.wr.jdbc.username}"/>
    <property name="password" value="${feima.wr.jdbc.password}"/>
    </bean>

    <!-- 配置事务管理器 1.使用dataSourceManager 2.指定dataSource -->
    <bean id="transactionManager"
    class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="feimaDataSource"/>
    </bean>
    <!--xml 配置-->
    <!--配置事务传播特性 1.指明使用哪个事务管理器 2.方法通配符配置传播特性-->
    <tx:advice id="transactionInterceptor" transaction-manager="transactionManager">
    <tx:attributes>
    <tx:method name="query*" propagation="SUPPORTS"/>
    <tx:method name="get*" propagation="SUPPORTS"/>
    <tx:method name="update*" propagation="REQUIRED"/>
    <tx:method name="save*" propagation="REQUIRED"/>
    <tx:method name="deal*" propagation="REQUIRED"/>
    <tx:method name="*" propagation="SUPPORTS"/>
    </tx:attributes>
    </tx:advice>

    <!--配置事务拦截器 1.通配符配置拦截哪些类、哪些方法、哪些返回值、哪些参数 2.指定切入点及通知 -->
    <aop:config>
    <aop:pointcut id="transactionPointCut" expression="execution(* com.jd.feima.crm.client.impl.remote.*.*(..))"></aop:pointcut>
    <aop:advisor advice-ref="transactionInterceptor" pointcut-ref="transactionPointCut"/>
    </aop:config>

    注解式事务配置
    <!-- 注解式事务 启用注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>


    事务详解
    事务传播特性:

    PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

    PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。

    PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。

    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

    PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

    PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。

    PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

    备注:
    可能大家还是对其中几个有点混淆,还是补充说明一下:
    PROPAGATION_NESTED: 嵌套事务类型,是相对上面提到的六种情况(上面的六种应该称为平面事务类型),打个比方我现在有一个事务主要有一下几部分:
          1,从A用户帐户里面减去100元钱
          2,往B用户帐户里面添加100元钱
           这样看和以前不同的事务可能没有什么区别,那我现在有点特殊的要求就是,A用户有3个帐户,B用户有2个帐户,现在我的要求就是只要再A用户的3个帐户里面任意一个减去100元,往B用户的两个帐户中任意一个里面增加100元就可以了!
           一旦你有这样的要求那嵌套事务类型就非常适合你!我们可以这样理解,
           一:将“从A用户帐户里面减去100元钱” 和 “往B用户帐户里面增加100元钱”我们暂时认为是一级事务操作
           二:将从A用户的3个帐户的任意一个帐户里面减钱看做是“从A用户帐户里面减去100元钱”这个一级事务的子事务(二级事务),同样把后面存钱的看成是另一个的二级事务。
          问题一:当二级事务失败被rollback一级事务会不会被rollback?
          答案:如果二级事务被trycatch , 一级事务是不会被rollback的
          问题二:什么时候这个一级事务会commit,什么时候会被rollback呢?
          我们主要看二级里面出现的情况,当所有的二级事务被commit了并且一级事务没有失败的操作,那整个事务就算是一个成功的事务,这种情况整个事务会被commit。
    当任意一个二级事务没有被commit, 且在一级事务里没有被try catch,那整个事务就是失败的,整个事务会被roolback。
    还是拿上面的例子来说明吧!如果我在a的三个帐户里面减钱的操作都被二级事务给rollback了,也就是3个帐户里面都没有减钱成功,整个事务就失败了就会被rollback。如果A用户帐户三个帐户里面有一个可以扣钱而且B用户的两个帐户里面也有一个帐户可以增加钱,那整个事务就算成功的,会被 commit。
     
    比较

    PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

    PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。

    PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

     
    • ServiceA {
    • /**
    • * 事务属性配置为 PROPAGATION_REQUIRED
    • */
    • voidmethodA(){ 
      insertA(a) ;
    • try {
    • ServiceB.methodB();
    • } catch (SomeException) {
    • // 执行其他业务, 如 ServiceC.methodC();
    • }
    • }
    •  
      B异常了
    if(A== required && B=required) {
        a插入成功
        b中异常之前的数据未回滚
        c执行
        //就是说B支持A的事务, B异常了,但A中trycatch了, 相当于事务commit
    }else if(A== required && B=requiredNew) {
        a插入成功
        B回滚
        c执行
    }else if(A== required && B=nested) {
        a成功
        b回滚
        c.执行
    }
     
    • A异常了
    if(A== required && B=required) {
       全部回滚
    }else if(A== required && B=requiredNew) {
        a回滚
        B成功
        c回滚
    }else if(A== required && B=nested) {
        全部回滚
     
    }
  • 相关阅读:
    JDK5的新特性
    反射(一)类加载器、反射、动态代理
    泛型(五)
    spring自定义注解实现登陆拦截器
    java国际化
    Codeforces 231A
    Codeforces 231A
    CCF CSP 201909-2 小明种苹果(续)
    CCF CSP 201909-2 小明种苹果(续)
    CCF CSP 201909-1 小明种苹果
  • 原文地址:https://www.cnblogs.com/chenge-0401/p/9520483.html
Copyright © 2020-2023  润新知