Spring事务

引用:Spring 中常用的两种事务配置方式以及事务的传播性、隔离级别

  • 事务的属性

  • 原子性

事务有一个原子组成,确保动作要么都完成,要么都不完成

  • 一致性

事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态
A给B转钱,无论怎么转,A和B的钱的总数都是一致的

  • 隔离性

多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰

  • 持久性

指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的

Spring的事务分为声明式编程式两种

  • 编程式事务 是在代码中加入处理事务的逻辑,在代码中显式的调用beginTransaction(),commit(),rollback()等

  • 声明式事务 建立在AOP上,本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完看情况进行回滚或者提交

区别:
声明式事务不需要在业务逻辑代码中惨杂事务管理的代码,做到了非侵入式的开发,但是不足的是编程式事务可以作用到代码块的级别,而声明式事务只能作用到方法

声明式事务又分为基于配置的和基于@Transactional注解

  • 基于配置

配置事务管理器

<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">       
          <property name="dataSource" ref="dataSource"></property>  
</bean>

配置需要加入事务的规则

<!-- 定义事务管理器 -->  
    <bean id="transactionManager"  
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="dataSource" />  
    </bean>  
    <!-- 下面使用aop切面的方式来实现 -->  
    <tx:advice id="TestAdvice" transaction-manager="transactionManager">  
        <!--配置事务传播性,隔离级别以及超时回滚等问题 -->  
        <tx:attributes>  
            <tx:method name="save*" propagation="REQUIRED" />  
            <tx:method name="del*" propagation="REQUIRED" />  
            <tx:method name="update*" propagation="REQUIRED" />  
            <tx:method name="add*" propagation="REQUIRED" />  
            <tx:method name="*" rollback-for="Exception" />  
        </tx:attributes>  
    </tx:advice>  
    <aop:config>  
        <!--配置事务切点 -->  
        <aop:pointcut id="services"  
            expression="execution(* com.website.service.*.*(..))" />  
        <aop:advisor pointcut-ref="services" advice-ref="TestAdvice" />  
    </aop:config>  
  • 基于@Transactional注解

配置事务管理器

<!-- 定义事务管理器 -->    
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    
    <property name="dataSource" ref="dataSource" />    
</bean>    
<!--使用注释事务 -->    
<tx:annotation-driven  transaction-manager="transactionManager" />

在需要加入事务的方法或者类上添加@Transactional

PS:annotation-driven 这样的注解,其含义就是支持注解

  • @Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置

  • @Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 <tx:annotation-driven/>元素的出现 开启 了事务行为

  • Spring事务7个传播级别

@Transactional(propagation=Propagation.REQUIRED)

定义在存在多个事务同时存在的时候,Spring应该如何处理这些事务的行为。这些属性在TransactionDefinition中定义

  1. PROPAGATION_REQUIRED:

支持当前事务,如果当前没有事务,就新建一个事务(默认)

  1. PROPAGATION_REQUIRES_NEW:

新建事务,如果当前存在事务,把当前事务挂起。新建的事务将和被挂起的事务没有任何关系,是两个独立的事务

  1. PROPAGATION_SUPPORTS:

支持当前事务,如果当前没有事务,就以非事务方式执行

  1. PROPAGATION_MANDATORY:

支持当前事务,如果当前没有事务,就抛出异常

  1. PROPAGATION_NOT_SUPPORTED:

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起

  1. PROPAGATION_NEVER:

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

  1. PROPAGATION_NESTED(没明白):

如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行

  • Spring事务5个隔离级别

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
  1. ISOLATION_DEFAULT:

这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.

  1. ISOLATION_READ_UNCOMMITTED:

这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。
这种隔离级别会产生脏读,不可重复读和幻像读

  1. ISOLATION_READ_COMMITTED:

保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据

  1. ISOLATION_REPEATABLE_READ:

这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。
它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

  1. ISOLATION_SERIALIZABLE :

这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。
除了防止脏读,不可重复读外,还避免了幻像读。

脏读:事务A对数据进行增删改,但是并未提交,在这时事务B获取了未提交的数据,然后事务A回滚,此时事务B就读到了脏数据
不可重复读:事务A读取了两次数据,在读取的两次中间,事务B修改了数据,导致事务A读取的两次结果不一样
幻读:事务A对一定范围的数据批量修改,此时事务B在范围内插入了一条新数据,则事务A失去了对新增数据的修改,用户发现表中还有没有修改的数据行,就好象发生了幻觉一样

  • Spring事务 只读

@Transactional(readOnly=true)
  • Spring事务 超时

@Transactional(timeout=30)
  • Spring事务 回滚

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