栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Spring】Spring事务使用、七大传播机制

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Spring】Spring事务使用、七大传播机制

事务

事务

  • 涉及到数据的一致性问题
  • 确保完整性和一致性
  • ACID原则:
    • 原子性:要么都成功,要么都失败;
    • 一致性:事务前后数据的完整性没有被破坏;
    • 隔离性:事务与事务之间相互隔离;
    • 持久性:事务完成后,数据的修改是永久的,不会因为机器重启等原因丢失;
  • 事务举例:
    insertUser();//可以正确执行
    deleteUser();//执行报错
    //结果:insert成功,delete失败
    

    普通情况下,delete未成功执行,但insert仍然会执行,我们如果想要这两个事务操作为一个整体,即如果delete失败,那么insert也不要执行。此时,我们就需要声明式事务;

Spring事务
  • MyBatis-Spring 允许 MyBatis 参与到 Spring 的事务管理中。而不是给 MyBatis 创建一个新的专用事务管理器,MyBatis-Spring 借助了 Spring 中的 DataSourceTransactionManager 来实现事务管理。
  • 一旦配置好了 Spring 的事务管理器,就支持 @Transactional 注解和 AOP 风格的事务配置。
  • 在事务处理期间,一个单独的 SqlSession 对象将会被创建和使用。当事务完成时,这个 session 会以合适的方式提交或回滚。
  • 事务配置好了以后,MyBatis-Spring 将会透明地管理事务。这样在你的 DAO 类中就不需要额外的代码了。
  • 声明式事务:AOP
  • 编程式事务:硬编码形式在代码中,进行事务管理
  1. 在spring配置文件中,配置事务管理器,并注入DataSource
    
    	
    
    

    注意:为事务管理器指定的 DataSource 必须和用来创建 SqlSessionFactory的是同一个数据源,否则事务管理器就无法工作了。

  2. 结合AOP实现事务的织入
    • 配置事务通知的切面:引入tx约束,设置事务管理器、事务装配的方法、以及事务传播特性:
      
      
          
              
                  
                  
                  
                  
                  
              
          
      
      

      Spring事务七大传播特性:
      REQUIRED: 支持当前事务,如果当前没有事务,就新建一个事务。【默认】
      SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
      MANDATORY: 支持当前事务,如果当前没有事务,就抛出异常。
      REQUERED_NEW: 新建事务,如果当前存在事务,就把当前事务挂起。
      NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
      NEVER: 以非事务方式执行操作,如果当前存在事务,就抛出异常。
      NESTED: 支持当前事务,如果当前存在事务,就执行一个嵌套事务,如果当前没有食物,就新建一个事务;

    • 将事务切面织入切入点:配置切入点+切入进切入点
      
          
          
      
      
    • 测试结果:delete执行失败后,insert也没执行;
  • 交由容器管理事务
    如果你正使用一个 JEE 容器而且想让 Spring 参与到容器管理事务的过程中,那么 Spring 应该被设置为使用 JtaTransactionManager 或由容器指定的一个子类作为事务管理器。最简单的方式是使用 Spring 的事务命名空间或使用 JtaTransactionManagerFactoryBean:

    
    
    @Configuration
    public class DataSourceConfig {
      @Bean
      public JtaTransactionManager transactionManager() {
        return new JtaTransactionManagerFactoryBean().getObject();
      }
    }
    

    在这个配置中,MyBatis 将会注入一个 SqlSession。 注意,如果你想使用由容器管理的事务,而不想使用 Spring 的事务管理,你就不能配置任何的 Spring 事务管理器。并必须配置 SqlSessionFactoryBean 以使用基本的 MyBatis 的 ManagedTransactionFactory:

    
      
      
        
      
    
    
    @Configuration
    public class MyBatisConfig {
      @Bean
      public SqlSessionFactory sqlSessionFactory() {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource());
        factoryBean.setTransactionFactory(new ManagedTransactionFactory());
        return factoryBean.getObject();
      }
    }
    
  • 编程式事务管理
    MyBatis 的 SqlSession 提供几个方法来在代码中处理事务。但是当使用 MyBatis-Spring 时,你的 bean 将会注入由 Spring 管理的 SqlSession 或映射器。也就是说,Spring 总是为你处理了事务。

    你不能在 Spring 管理的 SqlSession 上调用 SqlSession.commit(),SqlSession.rollback() 或 SqlSession.close() 方法。如果这样做了,就会抛出 UnsupportedOperationException 异常。在使用注入的映射器时,这些方法也不会暴露出来。

    无论 JDBC 连接是否设置为自动提交,调用 SqlSession 数据方法或在 Spring 事务之外调用任何在映射器中方法,事务都将会自动被提交。

    如果你想编程式地控制事务,使用PlatformTransactionManager 手工管理事务。

    public class UserService {
      private final PlatformTransactionManager transactionManager;
      public UserService(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
      }
      public void createUser() {
        TransactionStatus txStatus =
            transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
          userMapper.insertUser(user);
        } catch (Exception e) {
          transactionManager.rollback(txStatus);
          throw e;
        }
        transactionManager.commit(txStatus);
      }
    }
    

    在使用 TransactionTemplate 的时候,可以省略对 commit 和 rollback 方法的调用。

    public class UserService {
      private final PlatformTransactionManager transactionManager;
      public UserService(PlatformTransactionManager transactionManager) {
        this.transactionManager = transactionManager;
      }
      public void createUser() {
        TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
        transactionTemplate.execute(txStatus -> {
          userMapper.insertUser(user);
          return null;
        });
      }
    }
    

    注意:虽然这段代码使用的是一个映射器,但换成 SqlSession 也是可以工作的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/858150.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号