九、Spring 声明式事务学习总结

文章目录

  • 一、声明式事务
    • 1.1 什么是事务
    • 1.2 事务的应用场景
    • 1.3 事务的特性(ACID)
    • 1.4 未使用事务的代码示例
    • 1.5 配置 Spring 声明式事务学习总结



一、声明式事务


1.1 什么是事务

  • 把一组业务当成一个业务来做;要么都成功,要么都失败!

    • 事务在项目开发中,十分的重要,涉及到数据的一致性问题,不能马虎!


1.2 事务的应用场景

  • 在我们日常开发中,具体的业务大多数都是操作数据库的增删改查,其中包含了很多原子性的数据库操作。当同一个业务中出现多个原子性的数据库操作时,为了数据的安全性,避免数据不同步的状况发生就需要用到事务。

    • 举个栗子,银行转账

      • 两个人来到银行进行转账的操作,A 需要转给 B 1000块钱,也就是 A 的钱减少一千,B 的钱增加一千。但是如果在转账途中,出现银行系统崩溃或者网络故障等状况导致 A 的钱确实是少了一千,但是 B 的钱并没有增加,这显然是不对的。这时候事务的功效就显示出来了,两个操作要么就都成功,要么直接事务回滚,让操作都失败,以此来保证数据的安全性和一致性。



1.3 事务的特性(ACID)

  • 原子性(Atomicity):事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;

  • 一致性(Consistency):执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;

  • 隔离性(Isolation):并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

  • 持久性(Durability):一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

只有保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!



1.4 未使用事务的代码示例

  • 项目背景 Spring + Mybatis ,将第八章的项目原封不动的粘过来,修改 mapper.xml ,将删除 SQL 改成错误的写法其他内容不变

  • 修改测试类(新增一条数据,在将这条数据删除)

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = "classpath:spring-config.xml")
    public class Test_SpringMyBatis {
    
        @Autowired
        private UsersMapper userMapper;
    
        @Test
        public void testFindUserList(){
            Users users = new Users();
            users.setId("4");
            users.setName("姚青");
            users.setPwd("123456");
            int i = userMapper.saveUser(users);
            int i3 = userMapper.deleteUsers(users);
    
        }
    
    }
    
  • 执行结果,可以看出执行到 delete 方法时候报错了,但是第一条新增添加成功了,这显然不是很合理
    九、Spring 声明式事务学习总结_第1张图片

九、Spring 声明式事务学习总结_第2张图片



1.5 配置 Spring 声明式事务学习总结

  • 上面的代码执行出来的结果明显是不符合真实情况的,所有这里需要配置 Spring 的声明式事务

    • 在 Spring 配置文件中新增配置

      • 使用Spring管理事务,需要导入头文件的约束 : tx

        xmlns:tx="http://www.springframework.org/schema/tx"
        
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx.xsd">
        
      • 配置 Spring 声明式事务

         
            <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
                <constructor-arg ref="dataSource"/>
            bean>
        
      • 配置好声明式事务之后,结合 Spring aop 实现事务的织入(这里需要引入 tx (事务))

        
        
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
            
            
            <tx:attributes>
                <tx:method name="add" propagation="REQUIRED"/>
                <tx:method name="delete" propagation="REQUIRED"/>
                <tx:method name="update" propagation="REQUIRED"/>
                <tx:method name="query" read-only="true"/>
                <tx:method name="*" propagation="REQUIRED"/>
            tx:attributes>
        tx:advice>
        
        
        <aop:config>
            
            <aop:pointcut id="txPointCut" expression="execution(* com.sys.mapper.*.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
        aop:config>
        
    • Spring 完整配置

      
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:context="http://www.springframework.org/schema/context"
             xmlns:tx="http://www.springframework.org/schema/tx"
             xmlns:aop="http://www.springframework.org/schema/aop"
             xsi:schemaLocation="http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans.xsd
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/tx
              http://www.springframework.org/schema/tx/spring-tx.xsd
              http://www.springframework.org/schema/aop
              https://www.springframework.org/schema/aop/spring-aop.xsd">
      
          
          <context:property-placeholder location="classpath:jdbc-config.properties"/>
      
          
          <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
              <property name="driverClassName" value="${jdbc.driver}"/>
              <property name="url" value="${jdbc.url}"/>
              <property name="username" value="${jdbc.username}"/>
              <property name="password" value="${jdbc.password}"/>
          bean>
      
          
          <bean id="sessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
              
              <property name="dataSource" ref="dataSource"/>
              
              <property name="configLocation" value="classpath:mybatis-config.xml"/>
              
              <property name="mapperLocations" value="classpath:mapper/*.xml"/>
          bean>
      
          
          <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
              
              <property name="basePackage" value="com.sys.mapper"/>
          bean>
      
          
          <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <constructor-arg ref="dataSource"/>
          bean>
      
          
          
          <tx:advice id="txAdvice" transaction-manager="transactionManager">
              
              
              <tx:attributes>
                  <tx:method name="add" propagation="REQUIRED"/>
                  <tx:method name="delete" propagation="REQUIRED"/>
                  <tx:method name="update" propagation="REQUIRED"/>
                  <tx:method name="query" read-only="true"/>
                  <tx:method name="*" propagation="REQUIRED"/>
              tx:attributes>
          tx:advice>
      
          
          <aop:config>
              
              <aop:pointcut id="txPointCut" expression="execution(* com.sys.mapper.*.*(..))"/>
              <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
          aop:config>
      
      beans>
      
  • 其他代码不变

    • 测试结果:执行到 delete 方法时,依然报错,但是数据库没有新增数据,事务回滚成功。

九、Spring 声明式事务学习总结_第3张图片

九、Spring 声明式事务学习总结_第4张图片

你可能感兴趣的:(spring,学习)