Spring | Spring事务管理

目录:

    • [1.Spring事务管理 "含义"](#1.Spring事务管理 “含义”)
    • [2.Spring事务管理的 三个"核心接口" :](#2.Spring事务管理的 三个“核心接口” :)
        • [2.1 PlatformTransactionManager 接口](#2.1 PlatformTransactionManager 接口)
        • [2.2 TransactionDefinition 接口](#2.2 TransactionDefinition 接口)
        • [2.3 TransactionStatus 接口](#2.3 TransactionStatus 接口)
    • 3.Spring事务管理的方式 (两种)
        • [3.1 声明式事务管理 (常用)](#3.1 声明式事务管理 (常用))
          • [基于 XML方式的声明式事务](#基于 XML方式的声明式事务)
          • [基于Annotation (注解) 方式的声明式事务 (常用)](#基于Annotation (注解) 方式的声明式事务 (常用))

作者简介 :一只大皮卡丘,计算机专业学生,正在努力学习、努力敲代码中! 让我们一起继续努力学习!

该文章参考学习教材 为:
《Java EE企业级应用开发教程 (Spring + Spring MVC +MyBatis)》 黑马程序员 / 编著

文章以课本知识点 + 代码为主线,结合自己看书学习过程中的理解和感悟 ,最终成就了该文章

文章用于本人学习使用 , 同时希望能帮助大家。

欢迎大家点赞👍 收藏⭐ 关注💖哦!!!

(侵权教材方可联系我,进行删除,如果雷同,纯属巧合)


1.Spring事务管理 "含义"

  • Spring JDBC 可以用来操作数据库 ,在实际开发中,操作数据库时 还会涉及 事务管理问题,为此Spring 提供了 专门用于事务处理API
  • Spring事务管理 简化了传统的事务管理流程,并且在一定程度上减少了开发者工作量
  • 使用Spring事务功能 ,要 导入 spring-tx.Jar 这个
    Spring事务管理的JAR包
    jar包 / maven( 依赖 ) 下载( 可自行按需下载JAR )

2.Spring事务管理的 三个"核心接口" :

  • spring-tx.jar 这个jar包是Spring 提供的用于事务管理依赖包

  • 在该jar包下的org.springframework.transaction 包中,可以看到 三个主要的接口 ( 三个核心接口 ) :
    PlatformTransactionManager (接口)TransactionDefinition (接口)TransactionStatus (接口)
    具体讲解如下

2.1 PlatformTransactionManager 接口
PlatformTransactionManager接口 (3个"事务操作方法")
  • PlatformTransactionManager接口Spring提供的平台事务管理器,主要用于管理事务 。该接口中提供3个事务操作方法,具体如下。

    TransactionStatus getTransaction ( TransactionDefinition definition ) :

    用于 获取事务状态信息
    void commit ( TransactionStatus status ) : 用于提交事务
    void rollback ( TransactionStatus status ) : 用于回滚事务

    ps :

    (在上面的3个方法 中,getTransaction ( TransactionDefinition definitin )方法会根据 TransactionDefinition 参数返回 一个 TransactionStatus对象TransactionStatus 对象就表示一个事务它被关联在当前执行的线程上。)

  • PlatormTransactionManager接口 只是代表事务管理接口 ,,它并不知道底层是如何管务 的,它 提供三个业务管理的方法事务管理过程 由于它的实现类完成

    (当底层 采用不同持久层技术 时,系统只需使用不同PlatformTransactionManager 实现类即可。

    PlatormTransactionManager接口 常见的实现类 有 :
    org.springframework.jdbc.datasource.DataSourceTransactionManager :用于配置 JDBC 数据源事务管理器。
    org.springframework orm.hibemate4 .HiberateTransationManager : 用于 配置Hiber事务管理器
    org.springframework.transaction.jta .JtaTransactionManager :用于配置 全局事理器

PlatformTransactionManager接口的 "实现类"
  • PlatormTransactionManager接口 只是代表事务管理接口 ,,它并不知道底层是如何管务 的,它 提供三个业务管理的方法事务管理过程 由于它的实现类完成

    (当底层 采用不同持久层技术 时,系统只需使用不同PlatformTransactionManager 实现类即可。

  • PlatormTransactionManager接口 常见的实现类 有 :
    org.springframework.jdbc.datasource.DataSourceTransactionManager :用于配置 JDBC 数据源事务管理器。

    ps :
    DataSourceTransactionManager 依赖于 数据源 ,要在其的property属性 中添加 dataSource.

    org.springframework orm.hibemate4 .HiberateTransationManager : 用于 配置Hiber事务管理器
    org.springframework.transaction.jta .JtaTransactionManager :用于配置 全局事理器

2.2 TransactionDefinition 接口
  • TransactionDefinition 接口事务定义 (描述 ) 的 对象 ,该对象中 定义了事务规则。并提供了 获取事务相关信息方法。(通过该接口提供方法获取"事务的信息")

  • TransactionDefinition 接口提供 的 能 "获取事务相关信息" 的方法 如下 :

    • String getName( ) :获取 事务对象名称

    • int getlsolationLevel( ) : 获取事务隔离级别

    • int getPropagationBehavior( ) : 获取事务传播行为

    • int getTimeout( ) : 获取事务超时时间

    • boolean isReadOnly( ) : 获取 事务是否只读

      ps :

      上述方法中,事务的传播行为 是指在同一个方法 中,不同操作前后所使用的事务传播行为很多种。

      事务管理 过程中,传播行为 可以控制是否需要创建事务 以及如何创建事务 ,通常情况下,数据的查询 不会影响原数据的改变,所以不需要进行事务管理,而对于数据的插入、更新和删除操作必须进行事务管理 。如果没有指定 事务的传播行为,Spring 默认传播行为REQUIRED

2.3 TransactionStatus 接口
  • TransactionStatus接口事务的状态,它描述了某一时间点上事务状态信息
  • 该接口中包含6个方法 ,具体如下。
    • void flush( ) : 刷新事务
    • boolean hasSavepoint( ) : 获取 是否存在保存点
    • boolean isCompleted() : 获 取事务是否完成
    • boolean isNewTransaction( ) : 获取 是否是新事务
    • boolean isRollbackOnly( ):获取 是否回滚
    • void setRollbackOnly( ): 设置事务回滚

3.Spring事务管理的方式 (两种)

  • Spring 中的 事务管理 分为两种方式 :

    编程式事务管理

    声明式事务管理 (常用 ) ,下面主要讲的内容也是 "声明式事务管理"。

  • 编程式事务管理 : 是通过编 写代码实现事务管理,包括定义事务的开始 、正常执行后的事务提交异常时 的事务回滚

  • 声明式事务管理: 是通过 AOP技术实现 的事务管理,其主要思想是将事务管理作为一个'切面"代码单独编写 ,然后通过AOP技术将 事务管理的 "切面" 代码织入业务目标类中。

    声明式事务管理 最大的优点 在于开发者无须 通过编程的方式来管理事务,只需在配置文件中 进行相关的事务规则声明 ,就可以将事务规则 应用到业务逻辑 中。这使得开发人员可以更加专注于核心业务逻辑代码的编写 ,在一定程度上减少了 工作量,提高了 开发效率,所以在实际开发中,通常都推荐 使用声明式事务管理

3.1 声明式事务管理 (常用)
  • Spring的 声明式事务管理 可以通过两种方式 来实现,
    一、基于XML的方式 ( 基于 XML方式 的声明式事务 ) ---通过xml配置文件 的方式来实现"事务管理"的功能。
    二、基于Annotation (注解)的方式常用 )---通过在代码中添加 "注解"的方式来实现"事务管理"的功能。
基于 XML方式的声明式事务
  • 基于XML方式的声明式事务管理 是通过在配置文件配置事务规则相关声明来实现的。

  • Spring2.0以后 ,提供了tx命名空间配置事务tx命名空间 下提供了 <tx:advice>元素 来配置事务的通知 (增强处理) 。 当使用 <tx:advice>元素配置了事务的增强处理后 ,就可以通过编写的AOP配置 ,让Spring自动对目标生成代理

    自动生成代理 目的是 : 让事务对每个"报错/方法"生效)。

配置配置<tx:advice>元素时,通常需要指定 idtransaction-manager 属性,其中id属性 是配置文件中的唯一标识transaction-manager 属性 用于指定事务管理器

除此之外,还需要配置 <tx:atributes>子元素该子元素 可通过配置多个 <tx:method>子元素 来配置执行事务的细节
<tx:advice>元素 及其子元素如下图所示:

(配置<tx:advice>元素的重点的配置<tx:method>元素)

  • <tx:method>元素的属性

    属性名称 描述
    name 该属性为必选属性,它指定了与事务属性相关的方法名。其属性值支持使用通配符。 : 如'get*'、'handle*'、 '*Order'等 如:<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
    propagation 用于指定事务的传播行为 ,默认值为 REQUIRED
    isolation 该属性用于指定事务的隔离级别 : READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ 和 SERIALIZABLE,其默认值为DEFAULT。
    read-only 该属性用于 指定事务是否只读,其默认值为 false
    timeout 该属性用于 指定事务超时的时间,其 -1,即永不超时。
    rollback-for 该属性用于 指定触发"事务回滚"异常类,在指定多个异常类时,异常类之间以英文逗号分隔。
    no-rolback-for 该属性用于 指定 "不触发" 事务回滚异常类,在指定多个异常类时,异常类之间以英文逗号分隔。
  • 基于 XML方式声明式事务 的"例子" 如下 :

    • 第一步导入依赖
      ①Spring框架的基本核心依赖
      ②Spring JDBC要导入的依赖 ③Spring事务的依赖

      事务管理 中要用到AOP知识点所需 的依赖 ⑤Junit4单元测试依赖
      获取spring框架基本核心jar包
      获取Spring JDBC要导入的依赖
      Spring事务的依赖
      事务管理中要用到的AOP知识点所需的依赖

      Junit单元测试所需的依赖

      maven仓库网址(可自行按需下载)

    • 第二步、创建Student类StudentDao接口StudentDaoImpl实现类 ,在接口中添加"转账方法 "。Student.java

      java 复制代码
      package com.myh.tx;
      
      public class Student {
          private Integer id; //学生id
          private String username; //用户名
          private String hobby;
          private Double money;
      
          public Integer getId() {
              return id;
          }
      
          public void setId(Integer id) {
              this.id = id;
          }
      
          public String getUsername() {
              return username;
          }
      
          public void setUsername(String username) {
              this.username = username;
          }
      
          public String getHobby() {
              return hobby;
          }
      
          public void setHobby(String hobby) {
              this.hobby = hobby;
          }
      
          public Double getMoney() {
              return money;
          }
      
          public void setMoney(Double money) {
              this.money = money;
          }
      
          @Override
          public String toString() {
              return "Student{" +
                      "id=" + id +
                      ", username='" + username + '\'' +
                      ", hobby='" + hobby + '\'' +
                      ", money=" + money +
                      '}';
          }
      }

      StudentDao.java

      java 复制代码
      package com.myh.tx;
      
      import java.util.List;
      
      public interface StudentDao { //接口
      
          /*
            转账方法
            outUser : 汇款人
            inUser  : 收款人
           */
          public void transfer(String outUser, String inUser, Double money);
      }

      StudentDaoImpl.java

      java 复制代码
      package com.myh.tx;
      
      import org.springframework.jdbc.core.JdbcTemplate;
      
      import java.util.List;
      
      public class StudentDaoImpl implements StudentDao {
          //操作数据库的过程是通过 JDBC核心类:JdbcTemplate 的方法来进行的
      
          //注入JdbcTemplate类
          private JdbcTemplate jdbcTemplate;
      
          //配置文件的对应的property属性给jdbcTemplate赋值
          public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
              this.jdbcTemplate = jdbcTemplate;
          }
      
      
          /**
            转账方法
            outUser : 汇款人
            inUser  : 收款人
           */
          /*
            在两个操作之间,添加了一行代码"inti= 1/0:;"来模拟系统运行时的突发性问题。如果没有事务控制,那么在转账操作执行后,收款用户的余额会增加,
            而汇款用户的余额会因为系统出现问题而不变,这显然是有问题的;
            -----添加 "事务管理" 则可解决这个问题
           */
          @Override
          public void transfer(String outUser, String inUser, Double money) {
             //收款时,"收款学生用户" 的金额 = 现有金额 + 所汇金额
              //sql语句修改student表的money数据
              String sql = "update student set money = money + ? where username = ?";
              this.jdbcTemplate.update(sql,money, inUser); // inUser  : 收款人
      
              //模拟系统运行时突发性情况
              //int i = 1 / 0;  //因为此处报错了,如果没有添加"事务管理",那么资金就会错乱了---要进行"事务管理"操作
      
              //汇款时,汇款用户的余额 = 现有余额 - 所汇余额
              this.jdbcTemplate.update("update student set money = money  - ? where username = ?", money, outUser);//outUser : 汇款人
          }
      
      }
    • 第三步、在applicationContext.xml①编写事务通知 配置"通知器 " (该通知器 可为 "事务管理 " 服务 )

      ps :

      在<aop:config>中配置<aop:advisor> : 通知器 ,将"切入点 " 和 tx:advice通知 进行整合

      applicationContext.xml

      xml 复制代码
      <?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: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/cache
             http://www.springframework.org/schema/cache/spring-cache.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">
      
      <!--  通过JDBC来连接数据库  -->
          <!--  1.配置数据源(dataSource)  -->
          <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
              <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
              <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
              <property name="username" value="root"/>
              <property name="password" value="root"/>
          </bean>
      
          <!--  2.配置JDBC的核心类: JdbcTemplate (JDBC模板类)  -->
          <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
              <property name="dataSource" ref="dataSource"/>
          </bean>
      
          <!--  
                3. ①将StudentDaoImpl加入到IOC容器中
                   ②将JdbcTemplate注入到StudentDaoImpl,让其进行调用核心类中的方法来操作数据库  
          -->
          <bean id="studentDao" class="com.myh.tx.StudentDaoImpl">
              <property name="jdbcTemplate" ref="jdbcTemplate"/>
          </bean>
      
      
      
          <!--  通过基于XML的声明式"事务管理"来为代码添加 "事务"功能  -->
          <!--  4.事务管理器 (PlatormTransactionManager : 平台事务管理器) -->
          <bean id="PlatormTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
              <!--  配置"平台事务管理器"的 "数据源"    -->
              <property name="dataSource" ref="dataSource"/>
          </bean>
      
          <!--  5.编写通知 : 对事务进行增强(通知) ,需要编写对切入点和具体执行事务细节 -->
          <tx:advice id="txAdvice" transaction-manager="PlatormTransactionManager">
              <tx:attributes>
                   <!--  name : 指定"事务"对哪些方法起作用。 * 表示对所有方法起作用 -->
                  <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" read-only="false"/>
              </tx:attributes>
          </tx:advice>
      
          <!--  6.编写aop,让spring自动对目标生成代理( 让事务对每个"报错/方法"生效),小使用AspectJ的表达式  -->
          <aop:config>
              <!--  配置切入点 (切入点即为要被增强处理的"方法")   -->
              <aop:pointcut id="txPointCut" expression="execution(* com.myh.tx.*.*(..))"/>
              <!--
                 (属于AspectJ中的知识点)配置"通知器" : 将"切入点" 和 "事务的通知"整合,来让事务功能生效
               -->
              <!--  配置"通知器" : AspectJ中的知识点为"事务管理服务"  -->
              <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
          </aop:config>
      
      </beans>

      在上述配置文件 中,首先启用了Spring 配置文件aoptxconte xt 3个命名空间(从配置数据源到声明事务管理器的部分都没有变化),然后定义了idPlatormTransactionManager事务管理器 ,接下来通过编写通知声明事务 ,最后通过声明AOP的方式Spring自动生成代理

  • 第四步、创建事务管理的"测试类" : TransactionTest.java

    java 复制代码
    	package com.myh.tx;
    	
    	import org.junit.Test;
    	import org.springframework.context.ApplicationContext;
    	import org.springframework.context.support.ClassPathXmlApplicationContext;
    	
    	    public class TransactionTest { //事务管理的"测试类"
    	
    	    @Test //单元测试
    	    public void XmlTransactionTest() {
    	        ApplicationContext applicationContext =
    	        new ClassPathXmlApplicationContext("com/myh/tx/applicationContext.xml");
    	        StudentDao studentDao = (StudentDao)applicationContext.getBean("studentDao");
    	        studentDao.transfer("小红", "小明", 50.0);
    	        //输出提示信息
    	        System.out.println("转账成功!!!");  //如果这一过程中报错的话,是会通过"事务管理"的知识点进行回滚的,不会造成数据错乱。
    	    }
    	}

    运行结果 描述 :
    如果没报错 ,则代码正常运行 ,数据正常变化。如果代码报错 ,则会进行回滚不会造成数据错乱

基于Annotation (注解) 方式的声明式事务 (常用)
  • Spring声明式事务管理 还可以通过 Annotation (注解)的方式 来实现 (即通过在代码中 添加 "注解 " 的方式来完成 "事务管理")。

  • 基于Annotation (注解) 方式的声明式事务 要完成步骤 :
    第一步、先在配置文件配置Spring JDBC

    xml 复制代码
    <?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: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/cache
           http://www.springframework.org/schema/cache/spring-cache.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">
    
    <!--  通过JDBC来连接数据库  -->
        <!--  1.配置数据源(dataSource)  -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <!--  2.配置JDBC的核心类: JdbcTemplate (JDBC模板类)  -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--  
              3. ①将StudentDaoImpl加入到IOC容器中
                 ②将JdbcTemplate注入到StudentDaoImpl,让其进行调用核心类中的方法来操作数据库  
        -->
        <bean id="studentDao" class="com.myh.tx.xml.StudentDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"/>
        </bean>
        
    </beans>
  • 第二步、在配置文件配置平台事务管理器 ( 其中要用到Spring JDBC ),和 注册 "事务注解驱动"

    xml 复制代码
     <!--
          以下为基于Annotation方式是声明式事务 : 需要①配置"平台事务管理器" ②注册"事务注解驱动" ③(在实际的代码中添加注解来获取"事务管理的功能")
          -->
        <!--  只需在配置文件中 注册"事务注解驱动"  -->
        <!--  4.事务管理器 (PlatormTransactionManager : 平台事务管理器) -->
        <bean id="PlatormTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--  配置"平台事务管理器"的 "数据源"    -->
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--  5.注册"事务注解驱动" : 让代码中添加"注解"就能有"事务管理"的效果  -->
        <tx:annotation-driven transaction-manager="PlatormTransactionManager"/>
  • 第三步、在需要使用事务 的Spring Bean类 或者 Bean类方法上 添加注解 @Transactional

    注解 添加在Bean类 上,则表示事务的设置对整个Bean类的所有方法都起作用 。添加在Bean类 中的某个方法 上,则表示事务的设置只对该方法有效

    使用 @Transactional注解 时,可以通过其参数配置事务详情

    @Transactional注解的参数及其描述 如下表所示 :

    参数名称 描述
    value 用于指定需要使用事务管理器,默认为"",value别名transactionManage
    transactionManager 指定事务的 限定符值,可用于 确定目标事务管理器,匹配特定的限定值 (或者的name值),默认"",其 别名value
    isolation 用于指定别的 隔离级别,默认为Isolation.DEFAULT (即底层事务 的隔离级别级别)
    noRollbackFor 用于指定 遇到特定异常时强制不回滚事务
    noRollbackForClassName 用于指定遇到特定的多个异常强制不回滚事务 。其属性值可以指定多个异常
    propagation 用于指定事务的 传播行为默认Propagation.REQUIRED
    read-only 用于指定事务是否只读默认falses
    参数名称 描述
    rollbackFor 用于指定遇到特定异常强制回滚事务
    rollbackForClassName 用于指定遇到特定的多个异常强制回滚事务。其属性值可以指定多个异常类名
    timeout 用于指定事务的超时时长 ,默认为TransactionDefinition .TIMEOUT _DEFAULT (即底层事务系统默认时间)。

    ps :

    实际开发 中,事务的配置信息 通常是在Spring的配置文件中完成的 ,而在业务层类 使用 @Transactional注解 即可,不需要配置@Transactional注解属性

  • 例子如

  • 例子如
    Student.java

    java 复制代码
    package com.myh.tx.annotation;
    
    public class Student {
        private Integer id; //学生id
        private String username; //用户名
        private String hobby;
        private Double money;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getHobby() {
            return hobby;
        }
    
        public void setHobby(String hobby) {
            this.hobby = hobby;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Student{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", hobby='" + hobby + '\'' +
                    ", money=" + money +
                    '}';
        }
    }

    StudentDao.java (接口)

    java 复制代码
    package com.myh.tx.annotation;
    public interface StudentDao { //接口
    
        /*
          转账方法
          outUser : 汇款人
          inUser  : 收款人
         */
        public void transfer(String outUser, String inUser, Double money);
    }

    StudentDao.java (实现类)

    java 复制代码
    package com.myh.tx.annotation;
    
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.transaction.annotation.Transactional;
    
    public class StudentDaoImpl implements StudentDao {
        //操作数据库的过程是通过 JDBC核心类:JdbcTemplate 的方法来进行的
    
        //注入JdbcTemplate类
        private JdbcTemplate jdbcTemplate;
    
        //配置文件的对应的property属性给jdbcTemplate赋值
        public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
    
        /**
          转账方法
          outUser : 汇款人
          inUser  : 收款人
    
          使用Spring事务的基于"Annotation(注解)"的方式来配置事务,通过注解即可让代码实现事务功能
         在类或类的方法中添加 @Transactional 注解,还可按需配置其对应的"属性"。
         */
        @Transactional //此处添加注解,来为该方法开启"事务管理"
        @Override
        public void transfer(String outUser, String inUser, Double money) {
           //收款时,"收款学生用户" 的金额 = 现有金额 + 所汇金额
            //sql语句修改student表的money数据
            String sql = "update student set money = money + ? where username = ?";
            this.jdbcTemplate.update(sql,money, inUser); // inUser  : 收款人
    
            //模拟系统运行时突发性情况
            //int i = 1 / 0;  //因为此处报错了,如果没有添加"事务管理",那么资金就会错乱了---要进行"事务管理"操作
    
            //汇款时,汇款用户的余额 = 现有余额 - 所汇余额
            this.jdbcTemplate.update("update student set money = money  - ? where username = ?", money, outUser);//outUser : 汇款人
        }
    
    }

    上述类的 transfer( ) 方法中,添加了 @Transactional 注解 ,以此来为该方法开启 "事务管理"。

    applicationContext.xml

    xml 复制代码
    <?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: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/cache
           http://www.springframework.org/schema/cache/spring-cache.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">
    
    <!--  通过JDBC来连接数据库  -->
        <!--  1.配置数据源(dataSource)  -->
        <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
            <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
            <property name="url" value="jdbc:mysql://localhost:3306/spring"/>
            <property name="username" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <!--  2.配置JDBC的核心类: JdbcTemplate (JDBC模板类)  -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--  
              3. ①将StudentDaoImpl加入到IOC容器中
                 ②将JdbcTemplate注入到StudentDaoImpl,让其进行调用核心类中的方法来操作数据库  
        -->
        <bean id="studentDao" class="com.myh.tx.xml.StudentDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"/>
        </bean>
    
    
    
        <!--
          以下为基于Annotation方式是声明式事务 : 需要①配置"平台事务管理器" ②注册"事务注解驱动" ③(在实际的代码中添加注解来获取"事务管理的功能")
          -->
        <!--  只需在配置文件中 注册"事务注解驱动"  -->
        <!--  4.事务管理器 (PlatormTransactionManager : 平台事务管理器) -->
        <bean id="PlatormTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <!--  配置"平台事务管理器"的 "数据源"    -->
            <property name="dataSource" ref="dataSource"/>
        </bean>
    
        <!--  5.注册"事务注解驱动" : 让代码中添加"注解"就能有"事务管理"的效果  -->
        <tx:annotation-driven transaction-manager="PlatormTransactionManager"/>
    
    </beans>

    TransactionTest.java (测试类)

    java 复制代码
    package com.myh.tx.annotation;
    
    import com.myh.tx.annotation.StudentDao;
    import org.junit.Test;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class TransactionTest {
    
        @Test
        public void annotationTest() {
            ApplicationContext applicationContext =
                    new ClassPathXmlApplicationContext("com/myh/tx/annotation/applicationContext.xml");
            StudentDao studentDao = (StudentDao)applicationContext.getBean("studentDao");
            studentDao.transfer("小红", "小明", 50.0);
            //输出提示信息
            System.out.println("转账成功!!!");  //如果这一过程中报错的话,是会通过"事务管理"的知识点进行回滚的,不会造成数据错乱。
        }
    }

    测试类的效果 是 :

    当代码不报错 时,自然能正常转账 ,但当代码报错 时,程序会自动进行 "事务管理" ,进行回滚不会让数据发送错乱

相关推荐
王ASC17 分钟前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web
撒呼呼18 分钟前
# 起步专用 - 哔哩哔哩全模块超还原设计!(内含接口文档、数据库设计)
数据库·spring boot·spring·mvc·springboot
是小崔啊18 分钟前
开源轮子 - Apache Common
java·开源·apache
因我你好久不见23 分钟前
springboot java ffmpeg 视频压缩、提取视频帧图片、获取视频分辨率
java·spring boot·ffmpeg
程序员shen16161125 分钟前
抖音短视频saas矩阵源码系统开发所需掌握的技术
java·前端·数据库·python·算法
夕泠爱吃糖26 分钟前
C++中如何实现序列化和反序列化?
服务器·数据库·c++
网络安全Jack37 分钟前
网络安全概论——身份认证
网络·数据库·web安全
Ling_suu1 小时前
SpringBoot3——Web开发
java·服务器·前端
alden_ygq1 小时前
etcd网关
服务器·数据库·etcd
张声录11 小时前
【ETCD】ETCD Leader 节点写入数据流程概览
数据库·etcd