• Spring05——Spring 如何实现事务管理


    在此之前,我们已经了解了 Spring 相关的基础知识,今天将为给位带来,有关 Spring 事务代理的相关知识。关注我的公众号「Java面典」,每天 10:24 和你一起了解更多 Java 相关知识点。

    事务管理方式

    在 Spring 项目中,我们可以用通过四种方式实现事务管理,分别是 编程式事务管理、基于 TransactionProxyFactoryBean的声明式事务管理、基于 @Transactional 的声明式事务管理 和 基于Aspectj AOP配置事务。其实现方式如下:

    编程式事务管理

    // JDBC 事务管理
    Connection connection = DriverManager.getConnection("connUrl", "username", "password");
    //关闭自动提交,此句代码会自动开启事务。默认为true,自动提交。
    connection.setAutoCommit(false);  
    
    String sql1 = "insert into user(name) values (?)";
    PreparedStatement preparedStatement1 = connection.prepareStatement(sql1);
    preparedStatement1.setString(1,"Java面典");
    preparedStatement1.executeUpdate(); 
    
    String sql2 = "update user set name=? where id=?";
    PreparedStatement preparedStatement2 = connection.prepareStatement(sql2);
    preparedStatement2.setString(1, "Java面典 new");
    preparedStatement2.setInt(2, 10);
    preparedStatement2.executeUpdate();  
    
    try{
         //提交事务
        connection.commit();  
    }catch (SQLException e){
        //失败就回滚
        connection.rollback();  
    } finally {
        preparedStatement1.close();
        preparedStatement2.close();
        connection.close();
    }
    

    基于 TransactionProxyFactoryBean的声明式事务管理

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd">
    	
    	<tx:annotation-driven transaction-manager="transactionManager"/>
    </beans>
    

    基于 @Transactional 的声明式事务管理

    @Service
    public class UserServiceImpl implements IUserService {
        
        @Transactional(transactionManager = "transactionManager", rollbackFor = Exception.class)
        @Override
        public void add(User user) {
            // todo 
        }
    }
    

    基于Aspectj AOP配置事务

    <!-- 事务管理器 -->
    <bean id="tracnsactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
        
    <tx:advice id="txAdvice" transaction-manager="myTracnsactionManager">
        <tx:attributes>
            <!-- 为连接点指定事务属性 -->
            <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
            <tx:method name="stockChange" isolation="DEFAULT" propagation="REQUIRED" rollback-for="StockException"/>
        </tx:attributes>
    </tx:advice>
        
    <aop:config>
        <!-- 切入点配置 -->
        <aop:pointcut expression="execution(* *..service.*.*(..))" id="point"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="point"/>
    </aop:config>
    

    事务传播机制

    Spring 的事务传播分为以下几个机制:

    • REQUIRED:如果有事务则加入事务,如果没有事务,则创建一个新的(默认值);

    • NOT_SUPPORTED:Spring 不为当前方法开启事务,相当于没有事务;

    • REQUIRES_NEW:不管是否存在事务,都创建一个新的事务,原来的方法挂起,新的方法执行完毕后,继续执行老的事务;

    • MANDATORY:必须在一个已有的事务中执行,否则报错;

    • NEVER:必须在一个没有的事务中执行,否则报错;

    • SUPPORTS:如果其他 bean 调用这个方法时,其他 bean 声明了事务,则就用这个事务,如果没有声明事务,那就不用事务;
      SUPPORTS类型的事务传播机制,是否使用事务取决于调用方法是否有事务,如果有则直接用,如果没有则不使用事务。

    • NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 REQUIRED 类似的操作;

    注意事项

    在 A 方法内,调用 B 方法时,存在以下规则:

    1. REQUIRED
      当两个方法的传播机制都是 REQUIRED 时,如果一旦发生回滚,两个方法都会回滚;
    2. REQUIRES_NEW
      当 A 方法传播机制为 REQUIRES_NEW ,会开启一个新的事务,并单独提交方法,所以 B 方法的回滚并不影响 A 方法事务提交;
    3. NESTED
      当 A 方法为 REQUIRED,B 方法为 NESTED 时,A 方法开启一个嵌套事务;
      当 A 方法回滚时,B 方法也会回滚;反之,如果 B 方法回滚,则并不影响 A 方法的提交。

    事务隔离级别

    TransactionDefinition 接口中定义了五个表示隔离级别的常量:

    • ISOLATION_DEFAULT:使用后端数据库默认的隔离界别,MySQL默认采用的REPEATABLE_READ 隔离级别,Oracle 默认采用的 READ_COMMITTED 隔离级别;

    • ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取,允许读取尚未提交的的数据变更,可能会导致脏读、幻读或不可重复读;

    • ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生;

    • ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生;

    • ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从 ACID 的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就说,该级别可以阻止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

    Spring 系列推荐

    Spring04——Spring MVC 全解析

    Spring03——有关于 Spring AOP 的总结

    Spring02——Spring 中 Bean 的生命周期及其作用域

    Spring01——你应该了解的,有关 IOC 容器的一切

  • 相关阅读:
    EasyUI Combobox组合框(模糊搜索、默认值绑定)
    Asp.Net下载文件时中途失败问题
    VS使用小技巧之——设置调试时启动项目和启动页
    VS使用小技巧之——给代码添加region
    VS使用小技巧之——引入整个文件夹
    VS使用小技巧之——任务列表
    FineUI给表格行内链接设置弹出窗体
    cnpm私服搭建和发布包
    阿里云产品术语和docker
    angularjs1.x的一些知识点整理
  • 原文地址:https://www.cnblogs.com/weechang/p/12608964.html
Copyright © 2020-2023  润新知