配置spring 事务

来源:互联网 发布:百度推广软件下载 编辑:程序博客网 时间:2024/05/24 03:19
一、准备工作:
    模拟买书的场景:
        1.输入书名买书
        2.账户余额减五
        3.书库数量减少一
    当书库数量不足时,如果不存在事务的话,则书库数量不变,但账户余额却减少了

二、配置声明式事务(注解的方式)
    在application.xml中配置:

    <!-- 配置事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 启动事务注解 -->
    <tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
三、在编写买书方法:
    /**
     * 事务的传播行为:一个事务方法被另一个事务方法调用,
     * 被调用的事务方法如何工作在事务中
     * 使用propagation 指定事务的传播行为,即当前的事务被另一个事务方法调用时
     */
    @Transactional(propagation=Propagation.REQUIRED)
    @Override
    public void buy(String name) {
        System.out.println("购书开始");
        int money = Integer.parseInt(selectCount(name))-5;
        if(money <0){
            throw new MyException("账户余额不足");
        }
        //更新账户余额
        updateCount(name);
        int num = Integer.parseInt(selectBookNum(name))-1;
        if(num <0){
            throw new MyException("库存不足");
        }
        //更新书库数量
        updateBook(name);
        System.out.println("购书完成");
    }

    MyException 为自定义的异常集成RuntimeException,
    因为spring声明式事务对运行时异常支持事务的回滚

四:事务的传播行为:
     事务的7种传播行为: 默认为REQUIRED
     PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
     PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
     PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
     PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
     PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
     PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
     PROPAGATION_NESTED如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务,
     则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行
    
五、编写买多本书的方法
    /**
     * 买多本书
     */
    @Transactional
    @Override
    public void buyButch(String name, int num) {
        for(int i=0;i<num;i++){
            //调用买单本书的方法
            testService.buy(name);
        }    
    }    
    
    当将buy 方法的事务注解改为:
    @Transactional(propagation=Propagation.REQUIRED_NEW) 时,
    买多本书的时候,当库存不足的时候之前的不回滚
    @Transactional(propagation=Propagation.REQUIRED) 时,
    买多本书的时候,当库存不足的时候之前的回滚

六:事务的隔离级别: 事务并发的时候,可能存在脏读,幻读,不可重复读
Isolation 属性一共支持五种事务设置,具体介绍如下:

使用isolation 来指定事务的隔离级别
常用:READ_COMMITTED 读与提交

DEFAULT 使用数据库设置的隔离级别 ( 默认 ) ,由 DBA 默认的设置来决定隔离级别 .
READ_UNCOMMITTED 会出现脏读、不可重复读、幻读 ( 隔离级别最低,并发性能高 )
READ_COMMITTED  会出现不可重复读、幻读问题(锁定正在读取的行)
REPEATABLE_READ 会出幻读(锁定所读取的所有行)
SERIALIZABLE 保证所有的情况不会发生(锁表)

七、异常回滚
    默认情况下spring 的声明式事务对所有的运行时异常进行回滚,也可以通过对已的属性进行设置
     noRollbackFor 对异常别回滚了
    @Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED
         ,noRollbackFor={MyException.class},readOnly=false,timeout=3)

    rollbackFor 可以指定异常进行回滚

    readOnly=false 设置只读属性,表示这个事务只读取数据,但不能更新数据
    这样可以帮助数据库优化引擎,若真的是一个只读数据库值的方法,应设置readOnly = true

    timeout 指定强制回滚之前,事务可以占用的时间,防止事务对数据库链接占用时间过长

八、基于XML文件的形式配置事务
    修改XML文件:
    <!-- 基于XML的形式配置事务 -->
    <!-- 1.配置事务管理器 -->
    <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="buy" propagation="REQUIRES_NEW"></tx:method>
            <!-- 针对所有的方法 -->
            <tx:method name="*"></tx:method>
            <!-- 针对get方法开头的为只读 -->
            <tx:method name="get*" read-only="true"></tx:method>
        </tx:attributes>
    </tx:advice>
    <!-- 3.配置事务切点 ,以及把事务切入点及事务属性关联起来: 作用在哪些类的哪些方法上-->
    <aop:config>
        <aop:pointcut expression="execution(* service.impl.*.*(..))" id="txPointCut"></aop:pointcut>
        <!-- 切点和事务关联 -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"></aop:advisor>
    </aop:config>

原创粉丝点击