zoukankan      html  css  js  c++  java
  • Spring中的事物管理----HelloWorld

    在学习Spring的事物管理之前明白先明白几个概念
    1什么是事物:事务就是一系列的动作, 它们被当做一个单独的工作单元. 这些动作要么全部完成, 要么全部不起作用
    例子说明:例如银行转账,A账户转账(转200)到B账户,涉及的动作就是A账户余额减少200,B账户余额增加200,把这两个动作当成一个工作单元,要么两个动作一起完成,要么两个动作都不起用

    2事物作用是什么:有四大特性,分别是:
    原子性(就是多个动作组成一个原子操作,要么一起完成,要么一起不起作用)
    一致性(就是事物完成后,数据和资源保持一致性)
    隔离性(可能有许多事务会同时处理相同的数据, 因此每个事物都应该与其他事务隔离开来, 防止数据损坏)
    持久性(一旦事务完成, 无论发生什么系统错误, 它的结果都不应该受到影响. 通常情况下, 事务的结果被写到持久化存储器中)

    Spring中的事物管理使用步骤:

    * ①使用事务来处理的步骤:(基于注解的方式)
    * 1先配置事务管理器(每个数据源Spring都有对应的事务管理器)(因为数据源管理器是管理数据源的,所以要添加数据源属性)

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

    * 2启用事务注解

    <!-- 启用事务注解 -->
        <tx:annotation-driven transaction-manager="transactionManager"/>

    * 3在需要管理的方法前面使用@Transactional,也可以放在类名前面,这样所有方法都会默认使用事务管理,这样就会把方法放入事务管理器,进行管理

    @Transactional
        @Override
        public void purchase(String username, String isbn) {
            
            //1. 获取书的单价
            int price = bookShopDao.findBookPriceByIsbn(isbn);
            
            //2. 更新数的库存
            bookShopDao.updateBookStock(isbn);
            
            //3. 更新用户余额
            bookShopDao.updateUserAccount(username, price);
        }


    * 4为什么在测试类中不能使用呢????


    ②基于xml配置的方式

        <!--1 配置事务管理器,因为配置管理器也是一个Bean所以也要像Bean那样配置而且也是根据数据源来管理事务的,所以也要配置数据源属性 -->
        <bean id="transactionManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
        </bean>
        
        <!-- 2配置配置事务属性 ,①使用哪个事务管理器,②配置事务的属性:例如传播属性,隔离界别,。(可以为特定的方法配置事务属性)-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 根据方法名指定事务属性 -->
            <tx:method name="checkOut" propagation="REQUIRES_NEW"/>
            <tx:method name="*"/>
        </tx:attributes>
        </tx:advice>
        
        <!-- 3配置事务的切入点:1事物在那个类的那个方法起作用,2要把切入点和事务属性关联起来,这里需要用到AOP知识, -->
        <aop:config>
        <aop:pointcut expression="execution(* com.jeremy.springTransaction.BaseXml.BookShopService.*(..))" id="txPointCut"/>
        <aop:pointcut expression="execution(* com.jeremy.springTransaction.BaseXml.cashier.*(..))" id="txPointCut"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        </aop:config>

     spring事物管理属性说明:

    事物传播行为介绍: 
    @Transactional(propagation=Propagation.REQUIRED) 
    如果有事务, 那么加入事务, 没有的话新建一个(默认情况下)
    @Transactional(propagation=Propagation.NOT_SUPPORTED) 
    容器不为这个方法开启事务
    @Transactional(propagation=Propagation.REQUIRES_NEW) 
    不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务
    @Transactional(propagation=Propagation.MANDATORY) 
    必须在一个已有的事务中执行,否则抛出异常
    @Transactional(propagation=Propagation.NEVER) 
    必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)
    @Transactional(propagation=Propagation.SUPPORTS) 
    如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

    事物超时设置:
    @Transactional(timeout=30) //默认是30秒

    事务隔离级别:
    @Transactional(isolation = Isolation.READ_UNCOMMITTED)
    读取未提交数据(会出现脏读, 不可重复读) 基本不使用
    @Transactional(isolation = Isolation.READ_COMMITTED)
    读取已提交数据(会出现不可重复读和幻读)
    @Transactional(isolation = Isolation.REPEATABLE_READ)
    可重复读(会出现幻读)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    串行化

    MYSQL: 默认为REPEATABLE_READ级别
    SQLSERVER: 默认为READ_COMMITTED

    脏读 : 一个事务读取到另一事务未提交的更新数据
    不可重复读 : 在同一事务中, 多次读取同一数据返回的结果有所不同, 换句话说, 
    后续读取可以读到另一事务已提交的更新数据. 相反, "可重复读"在同一事务中多次
    读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据
    幻读 : 一个事务读到另一个事务已提交的insert数据

    @Transactional注解中常用参数说明

    参 数 名 称

    功 能 描 述

    readOnly

    该属性用于设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。例如:@Transactional(readOnly=true)

    rollbackFor

    该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:

    指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

    指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

     续表)

    参 数 名 称

    功 能 描 述

    rollbackForClassName

    该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。例如:

    指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")

    指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})

    noRollbackFor

    该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:

    指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)

    指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})

    noRollbackForClassName

    该属性用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。例如:

    指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")

    指定多个异常类名称:

    @Transactional(noRollbackForClassName={"RuntimeException","Exception"})

    propagation

    该属性用于设置事务的传播行为,具体取值可参考表6-7。

    例如:@Transactional(propagation=Propagation.NOT_SUPPORTED,readOnly=true)

    isolation

    该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置

    timeout

    该属性用于设置事务的超时秒数,默认值为-1表示永不超时

    注意的几点:
    1 @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能.

    2用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚.默认遇到运行期例外(throw new RuntimeException("注释");)会回滚,即遇到不受检查(unchecked)的例外时回滚;而遇到需要捕获的例外(throw new Exception("注释");)不会回滚,即遇到受检查的例外(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚 要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .如果让unchecked例外不回滚: @Transactional(notRollbackFor=RunTimeException.class)
    如下:
    @Transactional(rollbackFor=Exception.class) //指定回滚,遇到异常Exception时回滚
    public void methodName() {
    throw new Exception("注释");

    }
    @Transactional(noRollbackFor=Exception.class)//指定不回滚,遇到运行期例外(throw new RuntimeException("注释");)会回滚
    public ItimDaoImpl getItemDaoImpl() {
    throw new RuntimeException("注释");
    }

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


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


    5、Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承 的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因 此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。

      
  • 相关阅读:
    086 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 03 面向对象基础总结 01 面向对象基础(类和对象)总结
    085 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 02 构造方法介绍 04 构造方法调用
    jQuery UI组件库Kendo UI使用技巧小分享
    Kendo UI ListView模板功能,让Web开发更轻松
    UI组件套包DevExpress ASP.NET Core v20.2新版亮点:全新的查询生成器
    Devexpress WinForms最新版开发.NET环境配置Visual Studo和SQL Server对应版本
    全新的桌面应用数据可视化呈现方式,Sankey Diagram控件你了解多少?
    java中的递归方法
    连接数据库查询 将查询结果写入exce文件中
    java连接mysql数据查询数据
  • 原文地址:https://www.cnblogs.com/jeremy-blog/p/4057261.html
Copyright © 2011-2022 走看看