zoukankan      html  css  js  c++  java
  • MyBatis事务处理

    一.MyBatis单独使用时,使用SqlSession来处理事务

    使用MyBatis,你可以写代码去控制事务操作。例如,提交事务和回滚事务。

    public class MyBatisTxTest { 
     
      private static SqlSessionFactory sqlSessionFactory; 
      private static Reader reader; 
     
      @BeforeClass 
      public static void setUpBeforeClass() throws Exception { 
        try { 
          reader = Resources.getResourceAsReader("Configuration.xml"); 
          sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); 
        } finally { 
          if (reader != null) { 
            reader.close(); 
          } 
        } 
      } 
       
      @Test 
      public void updateUserTxTest() { 
        SqlSession session = sqlSessionFactory.openSession(false); // 打开会话,事务开始 
         
        try { 
          IUserMapper mapper = session.getMapper(IUserMapper.class); 
          User user = new User(9, "Test transaction"); 
          int affectedCount = mapper.updateUser(user); // 因后面的异常而未执行commit语句 
          User user = new User(10, "Test transaction continuously"); 
          int affectedCount2 = mapper.updateUser(user2); // 因后面的异常而未执行commit语句 
          int i = 2 / 0; // 触发运行时异常 
          session.commit(); // 提交会话,即事务提交 
        } finally { 
          session.close(); // 关闭会话,释放资源 
        } 
      } 
    } 

    xml配置文件:

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 
      <property name="dataSource" ref="dataSource"/> 
      <property name="transactionFactoryClass"> 
        <value>org.apache.ibatis.transaction.managed.ManagedTransactionFactory"/> 
      </property> 
    </bean> 

    缺点:可能会在每一个方法中,都需要添加事务的提交、回滚、关闭等,过于繁琐。

    二.和Spring集成后,使用Spring的事务管理

    事务管理方式:spring支持编程式事务管理和声明式事务管理两种方式。

    1、@ Transactional  声明式事务处理

    (1)为了使用Spring的事务处理能力,我们需要配置TransactionManager在Spring的配置文件中。

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

    (2)一旦DataSourceTransactionManager配置好了,你可以在Spring中以你通常的做法来配置事务。在事务处理期间,一个单独的SqlSession对象将会被创建和使用。当事务完成时,这个session会以合适的方式提交或回滚。这个dataSource涉及到的需要事务处理的相同的dataSource,这个将会用到SqlSessionFactory的bean中。

    基于注解的事务处理特性,Spring需要先使用下面的配置:

    <!-- 事务管理器 --> 
    <bean id="transactionManager" 
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
        <property name="dataSource" ref="dataSource" /> 
    </bean> 
     
    <!-- 事务注解驱动,标注@Transactional的类和方法将具有事务性 --> 
    <tx:annotation-driven transaction-manager="transactionManager" /> 
     
    <!-- 业务逻辑服务 -->
    <bean id="userService" class="com.john.hbatis.service.UserService" /> 

     现在你可以在Spring的服务的Bean中注解@ Transactional。这个注解表明每个方法都是Spring来管理的。如果方法成功处理,那么Spring就会提交事务;如果在处理过程出现了错误,那么事务就会被回滚。当然,Spring将会关心MyBatis的转换过程是否出现Exceptons的DataAccessExceptions的异常栈。

    @Service("userService") 
    public class UserService { 
     
      @Autowired 
      IUserMapper mapper; 
     
      public int batchUpdateUsersWhenException() { // 非事务性 
        User user = new User(9, "Before exception"); 
        int affectedCount = mapper.updateUser(user); // 执行成功 
        User user2 = new User(10, "After exception"); 
        int i = 1 / 0; // 抛出运行时异常 
        int affectedCount2 = mapper.updateUser(user2); // 未执行 
        if (affectedCount == 1 && affectedCount2 == 1) { 
          return 1; 
        } 
        return 0; 
      } 
     
      @Transactional 
      public int txUpdateUsersWhenException() { // 事务性 
        User user = new User(9, "Before exception"); 
        int affectedCount = mapper.updateUser(user); // 因后面的异常而回滚 
        User user2 = new User(10, "After exception"); 
        int i = 1 / 0; // 抛出运行时异常,事务回滚 
        int affectedCount2 = mapper.updateUser(user2); // 未执行 
        if (affectedCount == 1 && affectedCount2 == 1) { 
          return 1; 
        } 
        return 0; 
      } 
    } 

    在测试类中加入:

    @RunWith(SpringJUnit4ClassRunner.class)  // 测试运行器,基于spring mvc模式
    @ContextConfiguration(locations = { "classpath:beans-da-tx.xml" }) // 引入配置文件
    public class SpringIntegrateTxTest { 
     
      @Resource 
      UserService userService; 
     
      @Test 
      public void updateUsersExceptionTest() { 
        userService.batchUpdateUsersWhenException(); 
      } 
     
      @Test 
      public void txUpdateUsersExceptionTest() { 
        userService.txUpdateUsersWhenException(); 
      } 
    } 

    (3)下面是配置applicationContext.xml的文件:

    <beans>
            <context:annotation-config />
            <context:component-scan base-package="com.owen.mybatis" />
            <context:property-placeholder
                location="classpath:application.properties" />
            <tx:annotation-driven transaction-manager="transactionManager"/>
            <bean id="transactionManager"
                class="org.springframework.jdbc.datasource.
                DataSourceTransactionManager">
                <property name="dataSource" ref="dataSource" />
            </bean>
            <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                <property name="basePackage" value="com.owen.mybatis.mappers" />
            </bean>
            <bean id="sqlSession"
                class="org.mybatis.spring.SqlSessionTemplate">
                <constructor-arg index="0" ref="sqlSessionFactory" />
            </bean>
            <bean id="sqlSessionFactory"
                class="org.mybatis.spring.SqlSessionFactoryBean">
                <property name="dataSource" ref="dataSource" />
                <property name="typeAliases"
                    value="com.owen.mybatis.domain.Student,
                    com.owen.mybatis.domain.Tutor"/>
                <property name="typeAliasesPackage"
                    value="com.owen.mybatis.domain"/>
                <property name="typeHandlers"
                    value="com.owen.mybatis.typehandlers.PhoneTypeHandler"/>
                <property name="typeHandlersPackage"
                    value="com.owen.mybatis.typehandlers"/>
                <property name="mapperLocations"
                    value="classpath*:com/mybatis3/**/*.xml" />
            </bean>
            <bean id="dataSource"
                class="org.springframework.jdbc.datasource.
                DriverManagerDataSource">
                <property name="driverClassName"
                    value="${jdbc.driverClassName}"></property>
                <property name="url" value="${jdbc.url}"></property>
                <property name="username" value="${jdbc.username}"></property>
                <property name="password" value="${jdbc.password}"></property>
            </bean>
        </beans>

    2、transactionTemplate  编程式事务处理

    在spring配置文件中写入:

    <!-- jdbc事务管理器 -->
        <bean id="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource">
                <ref local="dataSource" />
            </property>
        </bean>
        <!--事务模板 -->
        <bean id="transactionTemplate"
            class="org.springframework.transaction.support.TransactionTemplate">
            <property name="transactionManager">
                <ref local="transactionManager" />
            </property>
            <!--ISOLATION_DEFAULT 表示由使用的数据库决定  -->
            <property name="isolationLevelName" value="ISOLATION_DEFAULT"/>
            <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED"/>
              <!-- <property name="timeout" value="30"/> -->
        </bean>
        <!-- 启动使用注解实现声明式事务管理的支持
        <tx:annotation-driven transaction-manager="txManager" /> -->

    示例代码:

    public class BankServiceImpl implements BankService {
    private BankDao bankDao;
    private TransactionTemplate transactionTemplate;
    ......
    public boolean transfer(final Long fromId, final Long toId, final double amount) {
        return (Boolean) transactionTemplate.execute(new TransactionCallback(){
           public Object doInTransaction(TransactionStatus status) {
           Object result;
               try {
                    result = bankDao.transfer(fromId, toId, amount);
               } catch (Exception e) {
                    status.setRollbackOnly();
                    result = false;
                    System.out.println("Transfer Error!");
               }
                    return result;
               }
          });
       }
    }

    扩展:Spring中的事务分为物理事务和逻辑事务;
    物理事务:就是底层数据库提供的事务支持,如JDBC或JTA提供的事务;
    逻辑事务:是Spring管理的事务,不同于物理事务,逻辑事务提供更丰富的控制,而且如果想得到Spring事务管理的好处,必须使用逻辑事务,因此在Spring中如果没特别强调一般就是逻辑事务;  

    优点:一旦事务创建之后,MyBatis-Spring将会透明的管理事务。在你的DAO或Service类中就不需要额外的代码了。

  • 相关阅读:
    Django model中的内嵌类(Class Meta)
    drf框架(二)
    drf框架(一)
    html、CSS 简单回顾
    前端vue框架(五)
    前端vue框架(四)
    前端Vue框架(三)
    前端vue框架(二)
    前端开发Vue框架(二)
    mysql 比较两个日期的时间差
  • 原文地址:https://www.cnblogs.com/xsl1995/p/9805112.html
Copyright © 2011-2022 走看看