Spring | Spring事务管理

news2024/11/27 14:43:36

目录:

    • 1.Spring事务管理 “含义”
    • 2.Spring事务管理的 三个“核心接口” :
        • 2.1 PlatformTransactionManager 接口
          • PlatformTransactionManager接口 (3个“事务操作方法”)
          • PlatformTransactionManager接口的 “实现类”
        • 2.2 TransactionDefinition 接口
        • 2.3 TransactionStatus 接口
    • 3.Spring事务管理的方式 (两种)
        • 3.1 声明式事务管理 (常用)
          • 基于 XML方式的声明式事务
          • 基于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

      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

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

      StudentDaoImpl.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 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 配置文件aoptxcontext 3个命名空间(从配置数据源到声明事务管理器的部分都没有变化),然后定义了idPlatormTransactionManager事务管理器,接下来通过编写通知声明事务,最后通过声明AOP的方式Spring自动生成代理

  • 第四步、创建事务管理的“测试类” : TransactionTest.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 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),和 注册 “事务注解驱动”

     <!--
          以下为基于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

    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 (接口)

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

    StudentDao.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 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 (测试类)

    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("转账成功!!!");  //如果这一过程中报错的话,是会通过“事务管理”的知识点进行回滚的,不会造成数据错乱。
        }
    }
    

    测试类的效果是 :
    当代码不报错时,自然能正常转账,但当代码报错时,程序会自动进行 “事务管理”,进行回滚不会让数据发送错乱

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1456420.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

flex布局、grid布局中的justify、align属性

一、grid中justify-content和justify-items的区别&#xff08;align同理&#xff09;&#xff08;flex中的justify-items属性无效&#xff09; justify-content:相对于父级&#xff0c;水平方向将整体进行对齐 justify-items:针对于每个格&#xff0c;将里面的内容进行对齐&a…

PAT (Basic Level) Practice | 数字分类

答案 #include <stdio.h> int main() {static int N, a, b[5], flag 0, c, flag1 0;scanf("%d", &N);for(int i 0; i < N; i) {scanf("%d", &a);if(a % 5 0) {if(a % 2 0) {b[0] a;}} else if(a % 5 1) {if(flag 0) {b[1] a;fl…

如何根据需求理解CPU、SoC和MCU的区别

在当今数字化的世界中&#xff0c;我们经常听到关于CPU、SoC和MCU的名词&#xff0c;它们都是计算机科学和电子工程领域中的重要组成部分。然而&#xff0c;这三者之间存在着明显的区别。本文将深入探讨CPU&#xff08;中央处理器&#xff09;、SoC&#xff08;系统芯片&#x…

如何使用Net2FTP部署本地Web网站并实现远程文件共享

文章目录 1.前言2. Net2FTP网站搭建2.1. Net2FTP下载和安装2.2. Net2FTP网页测试 3. cpolar内网穿透3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 文件传输可以说是互联网最主要的应用之一&#xff0c;特别是智能设备的大面积使用&#xff0c;无论是个人…

重启项目后Session依旧存在的问题研究

1. 背景 最近在开发对接智谱AI超拟人大模型&#xff0c;放了方便在pom.xml中引入了热部署相关的依赖。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</sco…

一元函数微分学【高数笔记】

1. 什么是微分&#xff1f;什么是微商&#xff1f; 2. 什么是函数的微分&#xff1f; 3. 在函数的微分中&#xff0c;有什么样的关系&#xff1f; 4. 一元函数的微分运用在什么题型中&#xff1f; 5. 什么是一元函数&#xff1f;

【JavaScript】实现下--刘谦春晚魔术:约瑟夫环的数学魅力!

2024年春晚刘谦的魔术堪称惊艳全场&#xff0c;那么他这个魔术实现的原理是什么呢&#xff1f;今天&#xff0c;就让咱们使用 JS 是实现这个魔术。 约瑟夫环问题简介&#x1f3b4;&#x1f50e; 约瑟夫环问题源自古罗马&#xff0c;由历史学家约瑟夫斯提出&#xff0c;而它的…

【STM32】硬件SPI读写W25Q64芯片

目录 基础知识回顾&#xff1a; SPI外设简介 SPI框图 主模式全双工连续传输 非连续传输 初始化SPI外设 核心代码 - 交换一个字节 硬件接线图 Code 程序配置过程 MySPI.c MySPI.h W25Q64.c W25Q64.h W25Q64_Ins.h main.c 基础知识回顾&#xff1a; 【STM32】SP…

Linux CentOS系统安装SQL Server并结合内网穿透实现公网访问本地数据

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

Android---Retrofit实现网络请求:Java 版

简介 在 Android 开发中&#xff0c;网络请求是一个极为关键的部分。Retrofit 作为一个强大的网络请求库&#xff0c;能够简化开发流程&#xff0c;提供高效的网络请求能力。 Retrofit 是一个建立在 OkHttp 基础之上的网络请求库&#xff0c;能够将我们定义的 Java 接口转化为…

汽车网络安全--关于供应商网络安全能力维度的思考

目录 1.关于CSMS的理解 2.OEM如何评审供应商 2.1 质量评审 2.2 网络安全能力评审 3.小结 1.关于CSMS的理解 最近在和朋友们交流汽车网络安全趋势时&#xff0c;讨论最多的是供应商如何向OEM证明其网络安全能力。 这是很重要的一环&#xff0c;因为随着汽车网络安全相关强…

一文解千惑:3D PCB电路板功能分区的关键要素

随着科技的不断发展&#xff0c;3D PCB电路板已成为电子工程领域的新宠。与传统的平面电路板相比&#xff0c;3D PCB电路板具有更多的优势&#xff0c;如更高的集成度、更强的信号传输能力和更小的体积。然而&#xff0c;要充分利用3D PCB电路板的优点&#xff0c;功能分区的关…

【C++】C++11中

C11中 1.lambda表达式2.可变参数模板3.包装器 1.lambda表达式 在前面我们学习过仿函数。仿函数的作用到底是干什么的呢&#xff1f; 它为了抛弃函数指针&#xff01; 主要是因为函数指针太难学了 就比如下面这个&#xff0c;看着也挺难受的。 它的参数是一个函数指针&#x…

【C项目】无头单向不循环链表

简介&#xff1a;本系列博客为C项目系列内容&#xff0c;通过代码来具体实现某个经典简单项目 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

ai图片放大老照片ai处理ps学习

老照片处理 1.bigjpg&#xff1a;AI人工智能图片放大 体验后评价&#xff1a;快速稳定 2.jpgHD&#xff1a;同bigjpg 另支持老照片上色 付费可用&#xff1a;破损修复&#xff0c;魔法动态照片 3.bigmp4&#xff1a;ai视频无损放大 4.jpgrm&#xff1a;ai擦除 利用2023年最先进…

Java入门及环境变量

文章目录 1.1 Java简介1.2 JDK的下载和安装1.3 第一个程序1.4 常见问题1.5 常用DOS命令1.6 Path环境变量 1.1 Java简介 下面我们正式进入Java的学习&#xff0c;在这里&#xff0c;大家第一个关心的问题&#xff0c;应该就是 Java 是什么&#xff0c;我们一起来看一下&#xf…

VMware Workstation 17安装教程:创建虚拟机

虚拟机软件的管理界面 新建虚拟机向导 设置硬件兼容性 设置系统的安装来源 选择操作系统的版本 未完待续&#xff0c;明天继续更新&#xff0c;如有疑问&#xff0c;点击链接加入群聊【信创技术交流群】&#xff1a;http://qm.qq.com/cgi-bin/qm/qr?_wv1027&kEjDhISXNgJlM…

CV论文--2024.2.19

1、Self-Play Fine-Tuning of Diffusion Models for Text-to-Image Generation 中文标题&#xff1a;自我对弈微调扩散模型&#xff0c;用于文本到图像生成 简介&#xff1a;在生成人工智能&#xff08;GenAI&#xff09;领域&#xff0c;微调扩散模型仍然是一个未被充分探索的…

App启动优化笔记 1

app大致的启动流程。有Launcher进程,system_server进程,zygote进程,APP进程。 Launcher进程:启动activity来启动应用 system_server进程:(ams是其中的一个binder):发送一个socket消息给Zygote。 zygote进程:收到消息后,fork新的进程,---》app进程启动 APP进程:…

Google发布能自我学习能力的Gemini 1.5

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 这波ai浪潮&#xff0c;进化的越来越强大和实用了&#xff0c;OpenAi刚发布了文生视频大模型Sora。而Google发布能了具有自我学习能力的Gemini 1.5。 Google 的大模型以及 AI 聊天机器人都采用 Gemini 这一名称。前…