zoukankan      html  css  js  c++  java
  • Spring事务讲解示例(转)

    Spring 事务Transaction
    1.事务的属性
    1.1 事务隔离IsolationLevel
    1.2 事务传播PropagationBehavior
    1.3 事务超时Timeout
    1.4 只读状态ReadOnly
    隔离级别、超时、只读状态都依赖于底层的数据库实现,Spring仅仅起了代理作用(MySQL的MyISAM引擎是无事务引擎,那么Spring是不可能带有事务管理功能的)。
    事务传播行为是Spring框架所特有的。
    2 使用Spring事务只需要了解PlatformTransactionManager、TransactionDefinition、TransactionStatus三个接口。
    2.1 TransactionDefinition描述了事务的配置。
    2.2 TransactionStatus描述当前事务的状态。
    2.3 PlatformTransactionManager使用TransactionDefinition来配置事务,使用TransactionStatus控制事务,对外提供了对事务的操作。
    3 事务传播行为详解(Spring定义了7种传播行为,3种最为常用的),事务传播行为发生在方法相互调用的时候(ServiceA.methodA调用ServiceB.methodB)。
    3.1  PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
        Spring只对public方法进行代理。目前,资源系统使用的默认事务传播行为就是PROPAGATION_REQUIRED。
    3.2  PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
    概念理解:PROPAGATION_REQUIRES_NEW 启动一个新的, 不依赖于环境的 "内部" 事务. 这个事务将被完全 commited 或 rolled back 而不依赖于外部事务, 它拥有自己的隔离范围, 自己的锁, 等等. 当内部事务开始执行时, 外部事务将被挂起, 内务事务结束时, 外部事务将继续执行.
    举例
    问题:用一张工单woId,操作100个产品,进行链路配置(1个产品对于一条链路),成功配置链路的产品则提交,失败配置的链路则回滚。
    分析:这说明100个产品是相互独立的,应该使用PROPAGATION_REQUIRES_NEW,每一个产品都是一个独立的事务。系统的默认行为已经不能满足当前需求,需要使用编程式事务管理。
    方法:
    for (int n = 0; n < 100; n++) {
        TransactionDefinition def = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = transactionManager.getTransaction(def);
        try{
        //产品配链路的业务逻辑
        configLink();
        transactionManager.commit(status);
        }catch(Exception e){
        transactionManager.rollback(status);
        }
    }//end for
    这是自热而然的方法,但是却是错误的方法,在for循环中,循环开启事务,并未生效(不清楚是什么原因)!
    将事务代码全部放入configLink()中即可。
    for (int n = 0; n < 100; n++) {configLink();}
    public void configLink(){
        TransactionDefinition def = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        TransactionStatus status = transactionManager.getTransaction(def);
        //产品配链路的业务逻辑
        transactionManager.commit(status);
    }
    3.3  PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
    概念理解:PROPAGATION_NESTED 开始一个 "嵌套的" 事务,  它是已经存在事务的一个真正的子事务. 嵌套事务开始执行时,  它将取得一个 savepoint. 如果这个嵌套事务失败, 我们将回滚到此 savepoint. 嵌套事务是外部事务的一部分, 通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。嵌套事务最有价值的地方, 它起到了分支执行的效果。
    举例
    问题:原有链路拆除方法抛出异常时,调用链路强制拆除方法。
    方法:
    try{
        oldMethodA();
    }catch(Exception e){
        newMethodB();
    }
    这种方式解决不了问题,oldMethodA与newMethodB处于同一事务中,oldMethodA中的操作在newMethodB是可见的,产生了脏数据。
    使用嵌套事务,将其改为:
    TransactionDefinition def = new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_NESTED);
    try{
        oldMethodA();
    }catch(Exception e){
        transactionManager.rollback(status);
        newMethodB();
    }
    另外,嵌套事务使用的是保存点,因此也可以使用status.createSavepoint()来替代。
    4 声明式事务管理@Transactional
    4.1 默认遇到throw new RuntimeException("..."),会回滚,需要捕获的throw new Exception("...");不会回滚。
    4.2 注解的属性在org.springframework.transaction.annotation.Transactional中定义。
    4.3 资源系统对所有*Service的public方法使用了事务代理,因此这些方法不能再次使用@Transactional注解,会发生重复注入的问题。

    http://www.cnblogs.com/njtcy/p/4439092.html

  • 相关阅读:
    HDFS上传文件
    SparkStreaming和Kafka的整合
    hadoop ha集群搭建
    Zookeeper安装
    hadoop完全分布式集群的搭建
    hadoop伪分布式集群的搭建
    java笔记之字符串,gc
    java笔记之字符串,gc
    java基础之short案例分析以及final关键字
    java基础之short案例分析以及final关键字
  • 原文地址:https://www.cnblogs.com/softidea/p/4440057.html
Copyright © 2011-2022 走看看