Spring | Spring事务管理

在这里插入图片描述

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

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

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值