• 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

  • 相关阅读:
    MVC 与传统的 webform 的比较
    Visual Studio 类模板的修改
    2015-3-3
    SQL SERVER类型与C#类型对照
    数据库连接串的配置
    Could not load file or assembly 'System.Web.Mvc' or one of its dependencies. The located assembly's manifest definition does not
    多条查询sql语句返回多表数据集
    URL和搜索引擎优化
    XPath 语法示例
    如何把数据库的某个字段更新为另一个字段
  • 原文地址:https://www.cnblogs.com/dobestself-994395/p/4272429.html
Copyright © 2020-2023  润新知