事务管理

大纲

Spring中事务的2种实现方式

四大事务隔离级别

七大事务传播行为

REQUIRED、REQUIRES_NEW、NESTED比较

Spring事务作用方法

 

 

Spring中事务的两种实现方式:

编程式事务管理(基于Java编程控制,很少使用)      

  -利用TransactionTemplate将多个DAO操作封装起来,可实现更细粒度的事务控制。

声明式事务管理(基于Spring的AOP配置控制,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务)

       -基于TransactionProxyFactoryBean的方式.(很少使用)

            需要为每个进行事务管理的类,配置一个TransactionProxyFactoryBean进行增强.

       -基于XML配置(经常使用)

            一旦配置好之后,类上不需要添加任何东西。

            如果Action作为目标对象切入事务,需要在<aop:config>元素里添加proxy-target-class="true"属性。原因是通知Spring框架采用CGLIB技术生成具有事务管理功能的Action类。

       -基于注解(配置简单,经常使用)
            在applicationContext.xml中开启事务注解配置。(applicationContext.xml中只需定义Bean并追加以下元素)

            <bean id="txManager" class="...">

           <tx:annotation-driven transaction-manager="txManager"/>

四大事务隔离级别:

ISOLATION_READ_UNCOMMITTED:读未提交

ISOLATION_READ_COMMITTED:读已提交

ISOLATION_REPEATABLE_READ:可重复读

ISOLATION_SERIALIZABLE:串行化

常量来源于java.sql.Connection

详情可参考 https://www.cnblogs.com/lyrb/p/10747814.html

七大事务传播行为

REQUIRED: 如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务。该设置是最常用的设置。

SUPPORTS: 如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。

MANDATORY: 如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。

REQUIRES_NEW: 创建新事务,如果当前存在事务,则挂起当前事务。新事务执行完毕后,再继续执行老事务。

NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则挂起当前事务。

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

NESTED:如果当前存在事务,则在嵌套事务内执行,如果当前没有事务,则执行与REQUIRED类似的操作。拥有多个可以回滚的保存点,内层回滚不会对外层事务产生影响,只对DataSourceTransactionManager有效。

传播行为比较

 1.REQUIRES_NEW和NESTED比较:

        REQUIRES_NEW开启新事务,需要两次commit,外层事务不会影响内层事务的提交/回滚,但REQUIRES_NEW的内层事务的异常,会影响外层事务的回滚

        NESTED为父子事务,实际上是借助JDBC的SavePoint实现的,属于同一个事务,只要一次commit。NESTED在创建内层事务之前创建一个单独的保存点SavePoint,子事务只回滚到SavePoint,父事务可选择回滚或不回滚(catch住不抛出),所以内层NESTED方法抛出异常被回滚,如果在外层方法内catch住不抛出,则不会影响外层事务。父事务回滚子事务一定回滚

2.REQUIRES_NEW和REQUIRED比较:

 

(1)不同的Service中调用方法:

       REQUIRED方法调用REQUIRES_NEW方法,内层方法抛出异常,被catch后不抛出,外层事务可以正常提交;

       如果REQUIRED方法调用REQUIRED,内层方法抛出异常,被catch后不抛出,后面的代码虽然可以执行下去,但外层事务最终还是会抛出rollback-only异常

(2)同一个Service中调用方法:

       如果REQUIRED方法调用REQUIRES_NEW方法,不会新建事务

       不管REQUIRED方法调用REQUIRES_NEW方法还是REQUIRED方法(非事务方法更是适用),内层方法抛出异常时,外层只要catch住不抛出,外层事务就可以正常提交

3.针对REQUIRED方法调用REQUIRES_NEW方法,不会新建事务的问题有两种解决方案:

(1)将两个方法写在不同的Service中

(2)方法写在同一个类中,但调用B方法的时候,将Service自己注入自己,用这个注入对象自己调用自己。

Spring事务作用方法

  1.事务配置在业务逻辑接口层:

    <aop:config proxy-target-class="false">
        <aop:pointcut id="serviceOperation"
            expression="execution(* com.XX..*Service.*(..) " />
        <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
    </aop:config>

 

  2.事物配置在业务逻辑实现层:

    <aop:config proxy-target-class="true">
        <aop:pointcut id="serviceOperation"
            expression="execution(* com.XX..*Service*.*(..) " />
        <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" />
    </aop:config>

  一种说法是:Spring IoC的配置是为了避免直接与实现类交互,便于扩展,建议配置在接口上。

  一种说法是:每个业务类一个接口有点麻烦呀,所以很多大牛都建议:“除非可以预见业务类将来一定会发生变化,否则不用写接口”,直接配置在实现类上。

  

https://blog.csdn.net/wangjunjun2008/article/details/53669951

https://www.cnblogs.com/dennyzhangdd/p/9602670.html

https://ask.csdn.net/questions/722300

posted @ 2019-08-19 22:23  留一日白  阅读(231)  评论(0编辑  收藏  举报