文档章节

Spring事务总结---事务概述及Spring事务的基本使用

sluggarddd
 sluggarddd
发布于 2016/03/28 18:51
字数 2854
阅读 135
收藏 16


一、事务概述

   这一节内容纯粹是为了写而写的,权当温习数据库知识和熟悉下怎么写博客了,谁让自己菜呢。:)

   看了许多别的博客和资料,事务两个字都快不认识了,那么其实事务的概念很简单,可以理解为一件事情,在计算机里,它就是一个操作序列。

   它相比于普通的事情不同的是,它必须服从ISO/IEC指定的ACID原则。

   A(Aotomicity)原子性,简单的说就是要么全部一起做完,要么都不做,即事务的不可分割性,若非使用特殊手段,如catch某些子事务的exception,否则当其中一个子事务失败,其他事务都将一起回滚。

   C(Consistency)一致性,即其保证是从一个正确的状态,转换成另一种正确的状态,即操作后数据不会被破坏,如转账时不会出现一方扣了钱而另一方却收不到的状况。

   I(Isolation)隔离性,在事务提交之前,它可能的结果不应该显示给其他事务。举个例子,如果一个事务为一个银行需要存入100元后存入200元,那当然不可以在存入100元后,就实例化到数据库被别的事务读取了存入100元后的结果,如果在存入200元时发生回滚不就出大事了嘛。所谓的隔离,就是需要保证各个事务之间是没有相互干扰的。

   D(Durability)持久性,其结果将正确的永久保存在数据库中,其他事务的失败不会对其造成影响。


    以上四个特性,经常受到讨论和争辩的莫过于一致性和隔离性了。所谓鱼与熊掌不可兼得,当我们需要兼顾所有的特性,可想而知,当安全性越高,其操作的顾忌和检查越多,性能也就越差。所以对于一致性和隔离性,又有着不同的规范等级。(垃圾文字功底)

    权衡之下可能出现的问题

    1、脏读,即读到不干净的数据。

     例子:(例子原址

    1)Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务) 
    2)Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地! 
    3)而财务发现操作有误,回滚了事务,Mary的工资又变为了1000, 像这样,Mary记取的工资数8000是一个脏数据。

    2、不可重复读,即在同一个事务中,重复读取却有不同的结果。

    例子:(例子原址

    1)在事务A中,Mary 读取了自己的工资为1000,操作并没有完成 
    2)在事务B中,这时财务人员修改了Mary的工资为2000,并提交了事务. 
    3)在事务A中,Mary 再次读取自己的工资时,工资变为了2000 

    3、幻读,即在同一事务中,可读取到其他事务提交后的结果,造成疑惑。

    例子:(例子原址

    1)A把所有的“黑色”改为“白色”

    2)B把所有的“红色”改为“黑色”

    3)A再查询黑色,却发现还有一批。


    隔离性的四个级别

    1、READ_UNCOMMITED(未授权读取),即可以读到未提交的数据。

    附上一个别人写的生动的例子

    公司发工资了,领导把5000元打到singo的账号上,但是该事务并未提交,而singo正好去查看账户,发现工资已经到账,是5000元整,非常高 兴。可是不幸的是,领导发现发给singo的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后singo实际的工资只有 2000元,singo空欢喜一场。(原址

    2、READ_COMMITED(授权读取),即其保证不会读到未提交的事务,但会造成不可重复读。

    附上一个别人写的生动的例子

    singo拿着工资卡去消费,系统读取到卡里确实有2000元,而此时她的老婆也正好在网上转账,把singo工资卡的2000元转到另一账户,并在 singo之前提交了事务,当singo扣款时,系统检查到singo的工资卡已经没有钱,扣款失败,singo十分纳闷,明明卡里有钱,为 何......

    出现上述情况,即我们所说的不可重复读 ,两个并发的事务,“事务A:singo消费”、“事务B:singo的老婆网上转账”,事务A事先读取了数据,事务B紧接了更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。原址

    3、REPEATABLE_READ(可重复读),即当读取时,不能进行更新。

     附上一个别人写的生动的例子

    当singo拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),singo的老婆就不可能对该记录进行修改,也就是singo的老婆不能在此时转账。

    虽然Repeatable read避免了不可重复读,但还有可能出现幻读。

    singo的老婆工作在银行部门,她时常通过银行内部系统查看singo的信用卡消费记录。有一天,她正在查询到singo当月信用卡的总消费金额(select sum(amount) from transaction where month = 本月)为80元,而singo此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后singo的老婆将singo当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,singo的老婆很诧异,以为出现了幻觉,幻读就这样产生了。

    注:Mysql的默认隔离级别就是Repeatable read。原址

    4、SERIALIZABLE(序列化),最高级别,在该级别下,事务顺序执行,那也就不会出现上面的问题了。

    这四个规范,从上至下安全性越高,性能越差。

    附一张哪都能看到的表

事务隔离级别 脏读 不可重复读 幻读
READ_UNCOMMITED Y Y Y
READ_COMMITED N Y Y
REPEATABLE_READ N N Y
SERIALIZABLE N N N



二、Spring事务用法

1、xml配置(搬运总结自开涛大神)

<!-- 事务管理的核心是事务管理器抽象,对于不同的数据访问框架(如Hibernate)通过实现策略接口PlatformTransactionManager,从而能支持各种数据访问框架的事务管理-->
<bean id="txManager"
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:advice transaction-manager="txManager" id="txAdvice">
    <tx:attributes>
    <!--表示将拦截以add开头的方法,被拦截的方法将应用配置的事务属性:propagation表示传播行为级别,默认是Required,isolation表示隔离级别
      name:定义与事务属性相关联的方法名,将对匹配的方法应用定义的事务属性,可以使用“*”通配符来匹配一组或所有方法,如“save*”将匹配以save开头的方法,而“*”将匹配所有方法;
      propagation:事务传播行为定义,默认为“REQUIRED”,表示Required,其值可以通过TransactionDefinition的静态传播行为变量的“PROPAGATION_”后边部分指定,如“TransactionDefinition.PROPAGATION_REQUIRED”可以使用“REQUIRED”指定;
      isolation:事务隔离级别定义;默认为“DEFAULT”,其值可以通过TransactionDefinition的静态隔离级别变量的“ISOLATION_”后边部分指定,如“TransactionDefinition. ISOLATION_DEFAULT”可以使用“DEFAULT”指定:
      timeout:事务超时时间设置,单位为秒,默认-1,表示事务超时将依赖于底层事务系统;
      read-only:事务只读设置,默认为false,表示不是只读;
      rollback-for:需要触发回滚的异常定义,以“,”分割,默认任何RuntimeException 将导致事务回滚,而任何Checked Exception 将不导致事务回滚;异常名字定义和TransactionProxyFactoryBean中含义一样
      no-rollback-for:不被触发进行回滚的 Exception(s);以“,”分割;异常名字定义和TransactionProxyFactoryBean中含义一样; -->
        <tx:method name="add*" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <!--切入点定义,定义名为"myPointcut"的aspectj切入点,切入点表达式为"execution(* com..zhw.service..*.*(..))"表示拦截com包及子包下的zhw. service包及子包下的任何类的任何方法-->
    <aop:pointcut id="myPointcut" expression="execution(* com..zhw.service..*.*(..))" />
    <!--切入点为myPointcut,通知为txAdvice。-->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut"/>
</aop:config>

    个人觉得xml配置的方式有点过于粗暴,在有事务嵌套的情况下有点难以处理(对我这种比较懒的人)。

2、Annotation声明

<!--在xml配置文件中开启注解事务管理支持即可-->
<tx:annotation-driven/>

    其具有三个属性

  • transaction-manager:指定事务管理器名字,默认为transactionManager

  • proxy-target-class:默认为false,false使用jdk动态代理,若为true则使用cglibs代理。设置为JDK代理和CGLIBS代理的主要区别是,使用JDK代理,@Transactional注释可以作用在接口和类及其方法上,而CGLIBS只能只用在类上,为了避免疏忽,建议就写在类上而不是接口上,而且,写在接口上事务是不支持继承的。

  • order:定义事务通知顺序,默认将顺序决定权交给AOP处理。

    在配置文件中开启注解事务管理后我们就可以使用@Transcational注释用于事务管理了。

@Transcational
public class SuperServiceImpl implements SuperService{

    public void add();

}


@Transactional
public class SubServiceImpl extends SuperServiceImpl implements SubService{

    public void update();
}

    以上是最常用的用法:

    1、将@Transactional注释作用在类上,默认该类所有方法都加入事务

    2、将@Transactional注释作用在父类上,其可以被子类集成。

   @Transactional注释有许多自定义的属性使他的功能更加丰富。

  • value:指定事务管理器,用于支持多事务管理器环境

  • isolation:指定事务隔离级别,默认『DEFAULT』

  • readOnly:事务是否只读,默认false。(即该事务开始后,其他事务所提交的数据,对该事务来说不可见,常用于多条查询语句在同一事务的情况)

  • timeout:事务超时时间,单位:秒。默认-1,表示超时将依赖于底层事务系统。

  • rollbackFor:指定一组异常类,遇到该异常将进行回滚,如若没有指定,那么将只会对unchecked异常进行回滚,而checked异常将不会回滚。

  • rollbackForClassname:作用同上。

  • noRollbackFor:指定某异常类,遇到该异常不回滚事务。

  • noRollbackForClassname:作用同上。

    注意事项:

    1、@Transactional注释只能作用于public方法上,其他修饰将被忽略。

    2、如果在接口,类,和方法上都指定了@Transactional注释,则优先级为方法->类->接口

    3、建议只在类上加@Transactional注释,而不是接口上。

    4、默认只会对unchecked异常进行回滚,最常见的为RuntimeException及其各种子类。

    那么Spring事务基本的使用方法就酱了 : ),目测已经可以满足百分之八九十需求了。



© 著作权归作者所有

sluggarddd
粉丝 7
博文 14
码字总数 11821
作品 0
程序员
私信 提问
Spring的事务管理实现原理初探

这里主要是通过分析部分源码进行剖析Spring事务管理的实现原理。 再分析源码前,现从理论上大概分析哈: 纯JDBC操作数据库的基本步骤: 1. 获取连接 Connection conn = DriverManager.getCon...

rockypeng
2014/01/19
0
0
☆聊聊Spring系列_Index

Spring经典详解 Spring事务机制详解 Spring配置事务五种方式 关于Spring加载classpath与classpath*的过程剖析 深入分析Spring 与 Spring MVC容器 Spring系列文章 【第1章 Spring概述与结构】...

陶邦仁
2015/12/09
1K
0
@Transaction必知必会

1. Spring事务的基本原理 事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编码式和声明式的两种方式。编程式事务指的是通过编码方式...

maskwang520
2018/04/15
0
0
Spring 深入理解事务原理

IT虾米的博客 一、事务的基本原理 Spring事务 的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步...

hgqxjj
2018/06/26
0
0
为什么用Spring来管理Hibernate?

为什么要用Hibernate框架?这个在《Hibernate介绍》博客中已经提到了。 既然用Hibernate框架访问管理持久层,那为何又提到用Spring来管理以及整合Hibernate呢? 首先我们来看一下Hibernate进...

晨曦之光
2012/08/22
468
0

没有更多内容

加载失败,请刷新页面

加载更多

java通过ServerSocket与Socket实现通信

首先说一下ServerSocket与Socket. 1.ServerSocket ServerSocket是用来监听客户端Socket连接的类,如果没有连接会一直处于等待状态. ServetSocket有三个构造方法: (1) ServerSocket(int port);...

Blueeeeeee
今天
6
0
用 Sphinx 搭建博客时,如何自定义插件?

之前有不少同学看过我的个人博客(http://python-online.cn),也根据我写的教程完成了自己个人站点的搭建。 点此:使用 Python 30分钟 教你快速搭建一个博客 为防有的同学不清楚 Sphinx ,这...

王炳明
昨天
5
0
黑客之道-40本书籍助你快速入门黑客技术免费下载

场景 黑客是一个中文词语,皆源自英文hacker,随着灰鸽子的出现,灰鸽子成为了很多假借黑客名义控制他人电脑的黑客技术,于是出现了“骇客”与"黑客"分家。2012年电影频道节目中心出品的电影...

badaoliumang
昨天
14
0
很遗憾,没有一篇文章能讲清楚线程的生命周期!

(手机横屏看源码更方便) 注:java源码分析部分如无特殊说明均基于 java8 版本。 简介 大家都知道线程是有生命周期,但是彤哥可以认真负责地告诉你网上几乎没有一篇文章讲得是完全正确的。 ...

彤哥读源码
昨天
15
0
jquery--DOM操作基础

本文转载于:专业的前端网站➭jquery--DOM操作基础 元素的访问 元素属性操作 获取:attr(name);$("#my").attr("src"); 设置:attr(name,value);$("#myImg").attr("src","images/1.jpg"); ......

前端老手
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部