Spring事务管理

事务回顾

事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败。事务操作能够保证数据操作的安全性。

以一个简单的银行转账案例说明,张三和李四账户都有两千元,现在张三要给李四转账1000元,那么需要两步操作,第一修改张三账户扣除1000元,第二修改李四账户增加1000元。这个转账操作不应该出现张三转账时由于某种原因钱转出去了但李四没收到。所以对于这样一组操作我们应该用事务来进行管理。那么一旦这组操作加入到了事务管理之中,它们就必须一起成功或者一起失败。

事务的特性(ACID特性)
  1. 原子性(Atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生要么都不发生
  2. 一致性(Consistency)
    一致性指事务前后数据的完整性必须保持一致
  3. 隔离性(Isolation)
    事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离
  4. 持久性(Durability)
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障也不应该对其有任何影响

Spring事务接口

Spring事务管理高层抽象主要包括3个接口:PlatformTransactionManager平台事务管理器,TransactionDefinition事务定义信息(隔离、传播、超时、只读),TransactionStatus事务具体运行状态。
Spring在进行事务管理的时候首先会根据事务定义信息,由事务管理器真正进行事务管理操作(事务提交、回滚等),在进行事务管理过程中事务会产生一些相应的状态,这些状态就保存在TransactionStatus中。

PlatformTransactionManager接口

Spring为不同的持久化框架提供了不同PlatformTransactionManager接口实现,通常我们都是使用前两种。

TransactionDefinition定义事务隔离级别

如果不考虑隔离性,会引发安全问题如下:脏读、不可重复读、幻读,隔离级别就是用来解决这几种读的问题的。

正常情况下数据库为我们提供了四种隔离级别,而default是spring提供的选择项。

TransactionDefinition定义事务传播行为

事务传播行为主要解决业务层方法之间的相互调用而产生的事务应该如何传递的问题。比如在a方法中调用了b方法
对于第一种类型来说如果a里面有事务,b方法就使用a的事务,如果a没有事务,b方法就新建事务,并把a内容包裹进来,意思是a和b这两个操作是在同一个事务之间的。类型2/3表示a没有事务,b方法就不使用事务/抛出异常。
后三种类型作为一类,表示a和b这两个操作没有在同一个事务中。
最后一种类型是嵌套事务,当a执行完成以后可以设置一个保存点,如果b发生异常之后可以回滚到保存点位置,或者最初始状态。

TransactionDefinition接口方法

Timeout: 事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制事务还没有完成,则自动回滚事务。
ReadOnly: 默认为false,也就是读写事务,如果设置只读事务则不允许对数据进行增删改,只读事务用于特定情景下的优化。

TransactionStatus接口

Spring事务管理

Spring支持两种方式事务管理方式,编程式事务管理和声明式事务管理。
编程式事务管理通过TransactionTemplate手动管理事务,在实际应用中很少使用。声明式事务管理是通过AOP实现的,开发中推荐使用(代码侵入性小)。

编程式事务管理

这种方式不推荐实际使用,仅提供实现思路供参考。
1.配置事务管理器TransactionManager,并在事务管理器中配置连接池dataSource属性。

2.配置事务管理的模版TransactionTemplate,并在事务管理模版中配置事务管理器属性。

3.在业务类中注入模版类,并调用其方法进行事务控制。

声明式事务管理

声明式事务管理共有3种实现方式,分别是基于TransactionProxyFactoryBean的方式、基于AspectJ的XML方式以及基于注解的方式。
由于第一种方式配置较为繁琐(需要为每个进行事务管理的类配置一个这样的Bean进行增强),通常实际开发不采用,这里我们只介绍后两种方式,也是实际开发常用的两种方式。

基于AspectJ的XML方式

基于这种方式我们只需要进行相关的配置即可,业务代码不需要做任何处理,注意在配置文件的头部需要添加aop和tx的命名空间。

    <!-- 配置连接池,这里以druid为例,连接池相关参数省略 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://xxx:3306/xxx"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root123"></property>
    </bean>
    
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 配置事务的通知:(事务的增强) -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- propagation:事务传播行为,isolation:事务隔离级别,read-only:只读 -->
            <!-- rollback-for:发生哪些异常回滚,no-rollback-for:发生哪些异常不回滚,timeout:超时时间 -->
            <tx:method name="delet*" propagation="REQUIRED" read-only="false" />
            <tx:method name="save*" propagation="REQUIRED" read-only="false" />
            <tx:method name="updat*" propagation="REQUIRED" read-only="false" />
            <tx:method name="*" propagation="SUPPORTS" read-only="true" />
        </tx:attributes>
    </tx:advice>
    <!-- AOP配置 -->
    <aop:config>
        <!-- 配置切入点 -->
        <aop:pointcut expression="execution(* com.rxy.*.service.*Service.*(..))"" id="pointcut1" />
        <!-- 配置切面 -->
        <aop:advisor pointcut-ref="pointcut1" advice-ref="txAdvice" />
    </aop:config>
基于注解的方式
  1. 添加配置
    <!-- 配置事务管理器 -->
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 开启注解事务 -->
    <tx:annotation-driven transaction-manager="transactionManager" />
  1. 使用注解@Transactional
    @Transactional可以作用于接口、接口方法、类以及类方法上。当作用于类上时,该类的所有 public 方法将都具有该类型的事务属性,同时,我们也可以在方法级别使用该标注来覆盖类级别的定义。
    我们更推荐将注解使用在类以及类方法上,而不是接口。并且@Transactional注解应该只被应用到 public 方法上。
//如果注解不定义任何属性,会使用其默认值,属性的含义参考xml方式的配置说明
@Transactional(propagation=Propagation.NOT_SUPPORTED)
public class AccountServiceImpl {
    //方法注解会覆盖类注解上的相同属性
    @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_UNCOMMITTED)
    public void transfer(final String out, final String in, final Double money){
        //业务逻辑,调用dao方法
    }
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容

  • 概要:2Spring事务管理接口(隔离级别,传播行为)、3接口介绍、4回滚原理 Spring事务的本质其实就是数据...
    hedgehog1112阅读 669评论 0 0
  • 1 什么是事务 生活中关于事务有一个常见的场景,即银行用户转账。简单的讲,转账可以分为下面 2 个步骤: 查看用户...
    millions_chan阅读 611评论 0 4
  • PartV.TransactiomManagement github 地址 https://github.com/...
    天幕_bc1a阅读 1,119评论 2 0
  • 对大多数Java开发者来说,Spring事务管理是Spring应用中最常用的功能,使用也比较简单。本文主要从三个方...
    sherlockyb阅读 3,203评论 0 18
  • 整理自张溪梦:数据分析师是怎样的一种人生?http://www.linkshop.com.cn/(kwthrmau...
    一只cherry阅读 815评论 0 4