zoukankan      html  css  js  c++  java
  • Spring中事务的配置与使用

    1.  spring的事务如何配置

        spring的声明式事务配置:

        1. <!-- 配置sessionFactory -->

             <bean id="sessionFactory"

                       class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

                       <property name="configLocation">

                                <value>/WEB-INF/classes/hibernate.cfg.xml</value>

                       </property>

             </bean> 

        2. 配置事务管理器

           <!-- 配置事务管理器 -->

             <bean id="transactionManager"

                       class="org.springframework.orm.hibernate3.HibernateTransactionManager">

                       <property name="sessionFactory">

                                <ref local="sessionFactory" />

                       </property>

             </bean>

        3. 配置事务特性

           <tx:advice id="txAdvice"  transaction-manager="transactionManager">

                       <tx:attributes>

                                 <tx:method name="add*" propagation="REQUIRED"/>

                        <tx:method name="update*" propagation="REQUIRED"/>

                        <tx:method name="del*" propagation="REQUIRED"/>

                        <tx:method name="*" read-only="true"/>

                    </tx:attributes>

           </tx:advice>

        4. 配置哪些类的哪些方法配置事务

           <aop:config>

               <aop:pointcut id="allManagerMethod" ession="execution(* com.yyaccp.service.impl.*.*(..))"/>

               <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod">

           </aop:config>

    Spring整合Ibatis事务管理管理配置参考:

    http://www.cnblogs.com/standcloud/articles/2602099.html

    http://www.cnblogs.com/Angi/articles/2007563.html

    要设置dataSource 的自动提交为false,让spring 去管理提交,自动提交默认是true

    advisor 是spring aop中的一个概念。
    advisor 可以翻译为增强器, 他是切入点(pointcut)和advice 的适配器。 它有两部门组成:一个增强以及一个说明在何处增强的切入点。增强器完整的模块化了一个方面(因为一个方面,就是由在什么地方增强和怎么增强组成的) 。 增强和切入点可以复用。

    Spring Transaction中有一个很重要的属性:Propagation。主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系。

    我晓得有点儿抽象,这也是为什么我想要写这篇博客的原因。看了后面的例子,大家应该就明白了。

    一、Propagation取值:

    REQUIRED(默认值):在有transaction状态下执行;如当前没有transaction,则创建新的transaction;

    SUPPORTS:如当前有transaction,则在transaction状态下执行;如果当前没有transaction,在无transaction状态下执行;

    MANDATORY:必须在有transaction状态下执行,如果当前没有transaction,则抛出异常IllegalTransactionStateException;

    REQUIRES_NEW:创建新的transaction并执行;如果当前已有transaction,则将当前transaction挂起;

    NOT_SUPPORTED:在无transaction状态下执行;如果当前已有transaction,则将当前transaction挂起;

    NEVER:在无transaction状态下执行;如果当前已有transaction,则抛出异常IllegalTransactionStateException。

    二、REQUIRED与REQUIRED_NEW

    上面描述的6种propagation属性配置中,最难以理解,并且容易在transaction设计时出现问题的是REQUIRED和REQURED_NEW这两者的区别。当程序在某些情况下抛出异常时,如果对于这两者不够了解,就可能很难发现而且解决问题。

    下面我们给出三个场景进行分析:

    场景一:

    ServiceA.java:

    public class ServiceA {
        @Transactional
        public void callB() {
            serviceB.doSomething();
        }
    }

    ServiceB.java

    public class ServiceB {
        @Transactional
        public void doSomething() {
            throw new RuntimeException("B throw exception");
        }
    }

    这种情况下,我们只需要在调用ServiceA.callB时捕获ServiceB中抛出的运行时异常,则transaction就会正常的rollback。

    场景二

    在保持场景一中ServiceB不变,在ServiceA中调用ServiceB的doSomething时去捕获这个异常,如下:

    public class ServiceA {
        @Transactional
        public void callB() {
            try {
                serviceB.doSomething();
            } catch (RuntimeException e) {
                System.err.println(e.getMessage());
            }
        }
    }

    这个时候,我们再调用ServiceA的callB。程序会抛出org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only这样一个异常信息。原因是什么呢?

    因为在ServiceA和ServiceB中的@Transactional propagation都采用的默认值:REQUREID。根据我们前面讲过的REQUIRED特性,当ServiceA调用ServiceB的时候,他们是处于同一个transaction中。如下图所示:

    当ServiceB中抛出了一个异常以后,ServiceB会把当前的transaction标记为需要rollback。但是ServiceA中捕获了这个异常,并进行了处理,认为当前transaction应该正常commit。此时就出现了前后不一致,也就是因为这样,抛出了前面的UnexpectedRollbackException。

    场景三

    在保持场景二中ServiceA不变,修改ServiceB中方法的propagation配置为REQUIRES_NEW,如下:

    public class ServiceB {
        @Transactional(propagation = Propagation.REQUIRES_NEW)
        public void doSomething() {
            throw new RuntimeException("B throw exception");
        }
    }

    此时,程序可以正常的退出了,也没有抛出UnexpectedRollbackException。原因是因为当ServiceA调用ServiceB时,serviceB的doSomething是在一个新的transaction中执行的。如下图所示:

    所以,当doSomething抛出异常以后,仅仅是把新创建的transaction rollback了,而不会影响到ServiceA的transaction。ServiceA就可以正常的进行commit。

    当然这里把ServiceA和ServiceB放在两个独立的transaction是否成立,还需要再多多考虑你的业务需求。

    Transaction不是一个新东西了,那对于transaction的使用会不会有一些模式?一些经验之谈呢?答案肯定是有的,以后博客再说。

     Pointcut 是指那些方法需要被执行"AOP",是由"Pointcut Expression"来描述的

    任意公共方法的执行:

    execution(* com.aptech.jb.epet.dao.hibimpl.*.*(..))
    这样写应该就可以了
    这是com.aptech.jb.epet.dao.hibimpl 包下所有的类的所有方法。。
    第一个*代表所有的返回值类型
    第二个*代表所有的类
    第三个*代表类所有方法
    最后一个..代表所有的参数。


    execution(public * *(..))
    任何一个以“set”开始的方法的执行:
    execution(* set*(..))
    AccountService 接口的任意方法的执行:
    execution(* com.xyz.service.AccountService.*(..))
    定义在service包里的任意方法的执行:
    execution(* com.xyz.service.*.*(..))
    定义在service包和所有子包里的任意类的任意方法的执行:
    execution(* com.xyz.service..*.*(..))

    带有@Transactional标注的所有类的任意方法.
    @within(org.springframework.transaction.annotation.Transactional)
    @target(org.springframework.transaction.annotation.Transactional)
    带有@Transactional标注的任意方法.
    @annotation(org.springframework.transaction.annotation.Transactional)
    ***> @within和@target针对类的注解,@annotation是针对方法的注解

    参数带有@Transactional标注的方法.
    @args(org.springframework.transaction.annotation.Transactional)
    参数为String类型(运行是决定)的方法.
    args(String)

    参考文献:

    http://blog.csdn.net/kkdelta/article/details/7441829

    http://blog.csdn.net/it_man/article/details/5074371

    http://blog.csdn.net/happyangelling/article/details/6228208

  • 相关阅读:
    leetcode 131. Palindrome Partitioning
    leetcode 526. Beautiful Arrangement
    poj 1852 Ants
    leetcode 1219. Path with Maximum Gold
    leetcode 66. Plus One
    leetcode 43. Multiply Strings
    pytorch中torch.narrow()函数
    pytorch中的torch.repeat()函数与numpy.tile()
    leetcode 1051. Height Checker
    leetcode 561. Array Partition I
  • 原文地址:https://www.cnblogs.com/dobestself-994395/p/4272429.html
Copyright © 2011-2022 走看看