Spring-事务机制

一、Spring事务

事务管理概述

Spring事务管理分为编程式事务管理和声明式事务管理两种

  1. 编程式事务:允许用户在实现代码中使用显式的方式调用beginTransaction()开启事务、commit()提交事务、rollback()回滚事务,从而可以达到精确定义事务的边界。
  2. 声明式事务管理:底层是建立在Spring AOP的基础上,在方式执行前后进行拦截,并在目标方法开始执行前创建新事务或加入一个已存在事务,最后在目标方法执行完后根据情况提交或者回滚事务。声明式事务的最大优点就是不需要编程,将事务管理从复杂业务逻辑中抽离,只需要在配置文件中配置并在目标方法上添加@Transactional注解即可实现

二、配置方式

1、概要

Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource、TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分。
DataSource、TransactionManager这两部分只是会根据数据访问方式有所变化,比如使用hibernate进行数据访问时,DataSource实际为SessionFactory,TransactionManager的实现为HibernateTransactionManager,关系图如下

image

2、tx标签拦截器

  1. 示例代码

    <tx:advice id="txAdvice" transaction-manager="txManager">
      <tx:attributes>
        <tx:method name="create*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" />
        <tx:method name="delete*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" />
        <tx:method name="update*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" />
        <tx:method name="get*" propagation="REQUIRED" read-only="true" timeout="300" />
        <tx:method name="*" propagation="REQUIRED" read-only="true" timeout="300" />
      </tx:attributes>
    </tx:advice>
    <aop:config>
      <!--其中第一个*代表返回值,第二*代表service下子包,第三个*代表方法名,“(..)”代表方法参数-->
      <aop:pointcut id="txPointcut" expression="execution(* com.xxx.xxx.xxx.service.*(..))" />
      <aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice" />
    </aop:config>   
    

3、全注解

  1. 说明

    虽然@Transactional注解可被应用于接口、接口方法、类及类的public方法,但建议在具体实现类上使@Transactional注解,因为接口上的注解不能被继承,这样会有隐患。当事务配置按如下方式,使用的是子类代理(CGLib)而非接口代理(JDK)时,对应目标类不会添加事务增强

  2. 示例代码

    开启注解事务
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
    <!--开启注解事务-->
    <tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />
        <bean id="tx" class="org.springframework.orm.jpa.JpaTransactionManager">
            <property name="entityManagerFactory" ref="entityManagerFactory"/>
        </bean>
        <!--因为我们是声明事务的注解在实现类上面  所有必须开启cglib类的代理模式-->
        <!--开启事务全注解-->
        <tx:annotation-driven transaction-manager="tx"/>
        <!--配置事物相关  start-->
       <!--在dao层使用自动管理EntityManager
       @PersistenceContext
        EntityManager em;
      -->
    

4、事务属性介绍

Spring事务属性定义在TransactionDefinition接口中,Spring4中该接口代码实现如下

public interface TransactionDefinition {
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int TIMEOUT_DEFAULT = -1;
    //事务的传播行为
    int getPropagationBehavior();
    //事务的隔离级别
    int getIsolationLevel();
    //事务超时时间
    int getTimeout();
    //是否只读
    boolean isReadOnly();
    String getName();
}

三、事务五大属性

1、说明

Spring事务属性就是事务的一些基本配置,描述了事务策略如何应用到方法上面,事务属性主要包含以下5个属性

​ Spring事务的传播属性

​ Spring事务的隔离级别

​ Spring事务是否只读

​ Spring事务回滚规则

​ Spring事务超时时间

2、Spring事务的传播属性

  1. @Transactional(propagation=Propagation.REQUIRED)

    如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)

  2. @Transactional(propagation=Propagation.NOT_SUPPORTED)

    容器不为这个方法开启事务

  3. @Transactional(propagation=Propagation.REQUIRES_NEW)

    不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行旧的事务

  4. @Transactional(propagation=Propagation.MANDATORY)

    必须在一个已有的事务中执行,否则抛出异常

  5. @Transactional(propagation=Propagation.NEVER)

    必须在一个没有的事务执行,否则抛出异常(与Propagation.MANDATORY相反)

  6. @Transactional(propagation=Propagation.SUPPORTS)

    如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他 bean没有声明事务,那就不用事务.

3、Spring事务的隔离级别

  1. @Transactional(isolation = Isolation.READ_UNCOMMITTED)

    读取未提交数据(会出现脏读, 不可重复读) 基本不使用

  2. @Transactional(isolation = Isolation.READ_COMMITTED)

    读取已提交数据(会出现不可重复读和幻读)

  3. @Transactional(isolation = Isolation.REPEATABLE_READ)

    可重复读(会出现幻读)

  4. @Transactional(isolation = Isolation.SERIALIZABLE)

    串行化

  5. @Transactional(isolation = Isolation.DEFAULT)

    默认级别,MYSQL: 默认为REPEATABLE_READ级别 SQLSERVER: 默认为READ_COMMITTED

  6. 总结

    隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
    大多数的数据库默认隔离级别为 Read Commited,比如 SqlServer、Oracle
    少数数据库默认隔离级别为:Repeatable Read 比如: MySQL InnoDB​

4、Spring事务超时时间

  1. TransactionDefinition 接口中定义了1个表示超时时间的常量**TIMEOUT_DEFAULT **,使用getTimeout()方法可以获取到超时时间,单位是秒。Spring事务超时时间,是指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。在Spring程序中超时时间设置的注解方式是设置timeout的值表示这个事务,true只读取数据但不更新数据,false表示可正常读写数据
  2. **@Transactional(timeout=30) **默认是-1,不超时

5、Spring事务是否只读

  1. 事务管理的只读属性是指对事务性资源进行只读操作或者是可读写操作。所谓事务性资源就是指那些被事务管理的资源,如数据源、JMS 资源,以及自定义的事务性资源等。如果确定只对事务性资源进行只读操作,那么我们可以将事务标志为只读的,以提高事务处理的性能。在TransactionDefinition 中以 boolean 类型来表示该事务是否只读,使用方法isReadOnly()来判断事务是否是只读的

6、Spring事务回滚规则

  1. @Transactional(rollbackFor=RuntimeException.class)

    用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则事务回滚。

  1. @Transactional(rollbackForClassName="RuntimeException")

    用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚

  1. @Transactional(noRollbackFor=RuntimeException.class)

    用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚

  1. @Transactional(noRollbackForClassName=RuntimeException.class)

    用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚

7、Spring事务注意事项

  1. 在需要事务管理的地方加@Transactional 注解。@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。
  2. @Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
  3. 注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。
  4. 通过 元素的 “proxy-target-class” 属性值来控制是基于接口的还是基于类的代理被创建。如果 “proxy-target-class” 属值被设置为 “true”,那么基于类的代理将起作用(这时需要CGLIB库cglib.jar在CLASSPATH中)。如果 “proxy-target-class” 属值被设置为 “false” 或者这个属性被省略,那么标准的JDK基于接口的代理将起作用。
  5. Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
  6. @Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。

四、注解常用参数

参数说明 描述
propagation @Transactional(propagation=Propagation.REQUIRED)
Isolation @Transactional(isolation = Isolation.READ_COMMITTED)读取已提交数据(会出现不可重复读和幻读)
timeout @Transactional(timeout=30)
readOnly @Transactional(readOnly=true)
rollbackFor @Transactional(rollbackFor=RuntimeException.class) 可以指定多个

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,277评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,777评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,946评论 0 245
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,271评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,636评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,767评论 1 221
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,989评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,733评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,457评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,674评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,155评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,518评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,160评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,114评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,898评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,822评论 2 280
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,705评论 2 273

推荐阅读更多精彩内容

  • 转载自:https://www.jianshu.com/p/8ddc01f23540 Spring事务机制主要包括...
    星海辰光大人阅读 340评论 0 0
  • Spring 事务属性分析 事务管理对于企业应用而言至关重要。它保证了用户的每一次操作都是可靠的,即便出现了异常的...
    壹点零阅读 1,244评论 0 2
  • 一、简介 Spring事务管理分为编程式事务管理和声明式事务管理两种, 声明式事务管理:底层是建立在Spring ...
    唯老阅读 381评论 0 2
  • Spring事务机制主要包括声明式事务和编程式事务,此处侧重讲解声明式事务,编程式事务在实际开发中得不到广泛使用,...
    七寸知架构阅读 3,631评论 1 53
  • 这部分的参考文档涉及数据访问和数据访问层和业务或服务层之间的交互。 Spring的综合事务管理支持覆盖很多细节,然...
    竹天亮阅读 1,010评论 0 0