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


一、事务概述

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

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

   它相比于普通的事情不同的是,它必须服从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_UNCOMMITEDYYY
READ_COMMITEDNYY
REPEATABLE_READNNY
SERIALIZABLENNN



二、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事务基本的使用方法就酱了 : ),目测已经可以满足百分之八九十需求了。



转载于:https://my.oschina.net/sluggarddd/blog/648710

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值