Spring的事务控制

基于AOP的声明事务控制

Spring事务编程概述

  • 事务是开发过程中必不可少的东西,使用JDBC开发时,我们使用connection对事务进行控制,使用MyBatis时,我们使用SqlSession对事物进行控制,缺点显而易见,当我们切换数据库访问技术时,事务控制的方法总会改变。Spring就在这些技术的基础上,提供了统一的控制事务接口。Spring的事务分为:编程式事务和声明式事务控制。
  • 事务控制方式解释
    编程式事务控制Spring提供了事务控制的类和方法,使用编程的方法对业务代码进行事务控制,事务控制代码和业务操作代码耦合在一起,开发中不使用
    声明式事务Spring将事务控制的代码封装起来,对外提供xml和注解的配置方式,通过配置的方式完成事务的控制,可以达到事务控制和业务操作代码的解耦,开发中推荐使用
  • Spring事务编程相关的类主要有以下三个

    • 类名功能
      PlatformTransactionManager平台事务管理器,抽象了不同的事务技术(如 JDBC、JTA)下的事务管理器。它定义了事务的开始、提交和回滚等操作接口,由具体实现提供相应的实现。Spring 提供了多种实现,不同持久层有不同实现方案,如 DataSourceTransactionManager、HibernateTransactionManager 和 JpaTransactionManager 等。
      TransactionDefinition事务定义,用于定义事务的隔离级别、超时时间等属性。Spring 定义了多种常量值,如 ISOLATION_DEFAULTISOLATION_READ_COMMITTEDISOLATION_REPEATABLE_READ 等隔离级别;TIMEOUT_DEFAULTTIMEOUT_NONE 等超时时间。
      TransactionStatus事务状态,包括是否新事务、是否已完成、是否回滚等状态。将该状态对象传递给事务管理器的 commit() 或 rollback() 方法可以控制事务的提交或回滚操作。
    • 虽然编程式事务控制我们不学习,但是编程式事务控制对应的类我们需要理解一下,因为我们在通过配置的方式进行声明式事务控制时也会看到这些类的影子。

搭建测试环境

  • 搭建转账的环境,dao层一个转出钱的方法,service是一个转账业务的方法,内部分别调用dao层转出钱和转入钱的方法,准备工作如下
    • 数据库准备一个账户表tb_account;
    • dao层准备一个AccountMapper,包括incrMoney和decrMoney两个方法
      • package com.example.Mapper;import org.apache.ibatis.annotations.Param;
        import org.apache.ibatis.annotations.Update;
        import org.springframework.stereotype.Repository;@Repository("accountMapper")
        public interface AccountMapper {@Update("update tb_account set money = money + #{money} where account_name=#{accountName}")public void incrMoney(@Param("accountName") String accountName, @Param("money") Integer money);@Update("update tb_account set money = money - #{money} where account_name=#{accountName}")public void decrMoney(@Param("accountName") String accountName, @Param("money") Integer money);
        }
        
    • service层(作为目标类,使用了注解的方式将其交给Spring容器管理,不需要再到xml配置文件中去配置)准备一个transferMoney方法,分别调用incrMoney和decrMoney方法
      • package com.example.Service.ServiceImpl;import com.example.Mapper.AccountMapper;
        import com.example.Service.AccountService;
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.stereotype.Service;@Service("accountService")
        public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;@Overridepublic void transferMoney(String outAccount, String inAccount, Integer money) {accountMapper.decrMoney(outAccount, money);System.out.println(outAccount + "转出" + money + "元");accountMapper.incrMoney(inAccount, money);System.out.println(inAccount + "转入" + money + "元");}
        }
        
    • 在applicationContext文件中进行Bean的管理配置
      • <?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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--    指定Spring组件扫描范围--><context:component-scan base-package="com.example"/><!--配置数据源信息--><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/db02"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--    配置SqlSessionFactoryBean,作用将SqlSessionFactoryBean存储到Spring容器中--><bean class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.example.Mapper"/></bean></beans>
        

        测试正常转账和异常转账

        • 正常测试代码
        • package com.example.Test;//import com.example.Config.MyBatisConfig;
          import com.example.Service.AccountService;
          import org.springframework.context.ApplicationContext;
          import org.springframework.context.annotation.AnnotationConfigApplicationContext;
          import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestAccount {public static void main(String[] args) {
          //        ApplicationContext context = new AnnotationConfigApplicationContext(MyBatisConfig.class);ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");AccountService accountService = (AccountService) context.getBean("accountService");accountService.transferMoney("tom", "lucy", 500);}
          }
          
        • 运行结果如下:

        • 错误测试,在业务层中加入错误
        •  
          package com.example.Service.ServiceImpl;import com.example.Mapper.AccountMapper;
          import com.example.Service.AccountService;
          import org.springframework.beans.factory.annotation.Autowired;
          import org.springframework.stereotype.Service;@Service("accountService")
          public class AccountServiceImpl implements AccountService {@Autowiredprivate AccountMapper accountMapper;@Overridepublic void transferMoney(String outAccount, String inAccount, Integer money) {accountMapper.decrMoney(outAccount, money);System.out.println(outAccount + "转出" + money + "元");int i = 1 / 0;accountMapper.incrMoney(inAccount, money);System.out.println(inAccount + "转入" + money + "元");}
          }
          
        • 同样运行上述测试代码

        • 运行结果如下(出现数据无法对应


基于xml声明式事务控制

  • 综合我们上面学到的AOP技术,很容易想到,可以使用AOP对Service的方法进行事务增强
    • 目标类:自定义的AccounServiceImpl,内部的方法是切点。不需要在xml配置文件中再次进行配置,已经使用注解方式,将其交给Spring容器管理
    • 通知类:Spring提供的,通知方法已经定义好,只需配置即可。
  • 分析
    • 通知类是Spring提供的,需要导入Spring事务相关的坐标
    • 配置目标类AccountServiceImpl
    • 使用advisor标签配置切面
  • 具体的配置文件如下
    • <?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:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!--    指定Spring组件扫描范围--><context:component-scan base-package="com.example"/><!--配置数据源信息--><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/db02"/><property name="username" value="root"/><property name="password" value="123456"/></bean><!--    配置SqlSessionFactoryBean,作用将SqlSessionFactoryBean存储到Spring容器中--><bean class="org.mybatis.spring.SqlSessionFactoryBean"><property name="dataSource" ref="dataSource"/></bean><bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"><property name="basePackage" value="com.example.Mapper"/></bean><!--    配置平台事务管理器--><bean name="transactionManager1" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!--    配置Spring提供的通知(advice)--><tx:advice id="AccountServiceAdvice" transaction-manager="transactionManager1"><tx:attributes><tx:method name="*"/></tx:attributes></tx:advice><!--    事务增强的AOP--><aop:config><!--        配置切点表达式--><aop:pointcut id="AccountService"expression="execution(* com.example.Service.ServiceImpl.AccountServiceImpl.*(..))"/><!--        配置织入关系,通知引用Spring所提供的--><aop:advisor advice-ref="AccountServiceAdvice" pointcut-ref="AccountService"/></aop:config></beans>
      

对于事务、AOP、代理对象的产生等相关知识,可以前往我的主页进行关键字搜索,自行查阅

  •  上述配置文件在最初配置文件的基础之上,使用AOP将目标方法进行事务管理
  • 具体的做法如下
    • 首先设置切点表达式,确定目标方法后,然后将切点表达式和Spring提供的通知进行织入,而此时需要配置Spring提供的通知,在配置该通知时需要配置事务平台管理器,最后将事务平台管理器配置好之后,就完成了对于目标方法的事务管理。
    • 事务平台管理器的作用
      • 事务的创建:事务平台管理器通过获取事务配置,从而创建一个新的事务对象,用于执行目标方法。

      • 事务的提交:在目标方法正常执行结束后,事务平台管理器会将事务提交,从而将所有修改操作永久保存到数据库。

      • 事务的回滚:在目标方法执行发生异常时,事务平台管理器会自动回滚事务,将所有修改操作撤销,保持系统数据的一致性。

      • 事务的传播行为:事务平台管理器可以根据配置,将事务从一个方法传播到另一个方法,以保证不同方法之间的数据一致性。

      • 事务隔离级别:事务平台管理器可以设置事务的隔离级别,从而决定不同事务之间可见的数据范围和并发度等问题。

      • Spring 支持多种事务平台管理器,例如 DataSourceTransactionManager、HibernateTransactionManager、JpaTransactionManager 等。不同的事务平台管理器对应着不同的持久化技术和数据库访问框架,在使用时需要注意选择合适的方案。

        当我们使用 Spring 进行事务管理时,事务平台管理器就是整个事务处理流程中的核心组件。它通过管理和控制事务,保证了数据操作的原子性、一致性、隔离性和持久性等特性,从而维护了数据库的完整性和系统的稳定性。

    • 再次运行最初存在人为错误的情况下,测试代码
    • 运行结果如下
      •  
        数据一致性得到了保障,AOP进行事务管理成功

 详解
  • 明天再来,p98

基于注解声明式事务控制

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++设计模式-桥接(Bridge)

目录 C设计模式-桥接&#xff08;Bridge&#xff09; 一、意图 二、适用性 三、结构 四、参与者 五、代码 C设计模式-桥接&#xff08;Bridge&#xff09; 一、意图 将抽象部分与它的实现部分分离&#xff0c;使它们都可以独立地变化。 二、适用性 你不希望在抽象和它…

桌面应用开发:Go 语言和 Web 技术的融合创新 | 开源日报 No.46

TheAlgorithms/Python Stars: 161.5k License: MIT 这个开源项目是一个用 Python 实现的算法库&#xff0c;旨在提供教育目的下使用的各种算法。 提供了大量常见算法的 Python 实现。适合学习和教育目的&#xff0c;可以帮助读者更好地理解不同类型的算法。 airbnb/javascri…

CSS3实现动画加载效果

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>加载效果</title><link rel"style…

数据结构与算法-(7)---栈的应用-(4)后缀表达式求值

&#x1f308;write in front&#x1f308; &#x1f9f8;大家好&#xff0c;我是Aileen&#x1f9f8;.希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流. &#x1f194;本文由Aileen_0v0&#x1f9f8; 原创 CSDN首发&#x1f412; 如…

1.7.C++项目:仿muduo库实现并发服务器之Poller模块的设计

项目完整在&#xff1a; 文章目录 一、Poller模块&#xff1a;描述符IO事件监控模块二、提供的功能三、实现思想&#xff08;一&#xff09;功能&#xff08;二&#xff09;意义&#xff08;三&#xff09;功能设计 四、封装思想五、代码&#xff08;一&#xff09;框架&#…

CLIP与DINOv2的图像相似度对比

在计算机视觉领域有两个主要的自监督模型:CLIP和DINOv2。CLIP彻底改变了图像理解并且成为图片和文字之间的桥梁&#xff0c;而DINOv2带来了一种新的自监督学习方法。 在本文中&#xff0c;我们将探讨CLIP和DINOv2的优势和它们直接微妙的差别。我们的目标是发现哪些模型在图像相…

WEB各类常用测试工具

一、单元测试/测试运行器 1、Jest 知名的 Java 单元测试工具&#xff0c;由 Facebook 开源&#xff0c;开箱即用。它在最基础层面被设计用于快速、简单地编写地道的 Java 测试&#xff0c;能自动模拟 require() 返回的 CommonJS 模块&#xff0c;并提供了包括内置的测试环境 …

UDP通信程序的详细解析

2.UDP通信程序 2.1 UDP发送数据 Java中的UDP通信 UDP协议是一种不可靠的网络协议&#xff0c;它在通信的两端各建立一个Socket对象&#xff0c;但是这两个Socket只是发送&#xff0c;接收数据的对象&#xff0c;因此对于基于UDP协议的通信双方而言&#xff0c;没有所谓的客户端…

JMeter学习第一、二、三天

首先&#xff0c;我们来了解一下到底什么是接口测试与性能测试&#xff1a; 接口测试 定义 接口测试主要关注系统组件之间的交互&#xff0c;确保各个接口按预期工作。这包括验证传递的数据、数据格式、调用的频率和其他与接口调用相关的任何限制。 目的 确保系统的各个组件可…

Qt中 QMap 类、QHash 类、QVector 类详解

目录 一、QMap 类 1.插入数据信息 2.删除数据信息 3.迭代器 4.STL类型迭代 5.key键/T键查找 6.修改键值 7. 一个键对应多个值 直接使用QMultiMap类来实例化一个QMap对象 二、QHash 类 三、QVector类 一、QMap 类 QMap<Key,T>提供一个从类型为 Key 的键到类型为…

解决WPF+Avalonia在openKylin系统下默认字体问题

一、openKylin简介 openKylin&#xff08;开放麒麟&#xff09; 社区是在开源、自愿、平等和协作的基础上&#xff0c;由基础软硬件企业、非营利性组织、社团组织、高等院校、科研机构和个人开发者共同创立的一个开源社区&#xff0c;致力于通过开源、开放的社区合作&#xff…

【MySQL】索引特性

目录 MySQL索引特性 索引的概念 认识磁盘 磁盘的结构 磁盘的随机访问&#xff08;Random Access&#xff09;与连续访问&#xff08;Sequential Access&#xff09; MySQL与磁盘交互的基本单位 索引的理解 观察主键索引现象 推导主键索引结构的构建 索引结构可以采用…

IPSG技术和IP组播

1&#xff0c;IPSG技术概述 实验&#xff1a; DHCP snooping IPSG 拓扑&#xff1a; 需求&#xff1a; 1&#xff0c;实现PC1 和PC2 动态获取IP地址 2, 在SW2 配置DHCP snooping 实现DHCP 服务器的安全 3, 在 连接PC 1 和 PC2 的 接口上 做IPSG &#xff0c;防止终端…

贪心算法+练习

正值国庆之际&#xff0c;祝愿祖国繁荣昌盛&#xff0c;祝愿朋友一生平安&#xff01;终身学习&#xff0c;奋斗不息&#xff01; 目录 1.贪心算法简介 2.贪心算法的特点 3.如何学习贪心算法 题目练习&#xff08;持续更新&#xff09; 1.柠檬水找零&#xff08;easy&…

​苹果应用高版本出现:“无法安装此app,因为无法验证其完整性”是怎么回事?竟然是错误的?

最近经常有同学私聊我问苹果应用签名后用落地页下载出现高版本是什么意思&#xff1f;我一脸懵&#xff01;还有这个操作&#xff1f;高版本是个啥玩意&#xff01;所以我就上了一下科技去搜索引擎搜索了下&#xff0c;哈哈哈&#xff0c;然后了解下来发现是这样的首先我们确定…

Kubernetes安装部署 1

本文主要描述kubernetes的安装部署&#xff0c;kubernetes的安装部署主要包括三个关键组件&#xff0c;其中&#xff0c;包括kubeadm、kubelet、kubectl&#xff0c;这三个组件的功能描述如下所示&#xff1a; Kubeadm 用于启动与管理kubernetes集群 Kubelet 运行在所有集群的…

Mac版快速切换工具:One Switch中文 for mac

One Switch是一款功能强大、体验极简的Mac菜单栏工具&#xff0c;适合需要频繁切换系统设置和启动应用程序的用户使用。通过它&#xff0c;用户可以更方便地完成日常操作&#xff0c;提高工作效率。 快速访问工具&#xff1a;One Switch提供了一个便捷的菜单栏图标&#xff0c;…

nodejs+vue晨拾酒馆管理系统elementui

晨拾酒馆管理系统&#xff0c;主要的模块包括管理员&#xff1b;系统首页、个人中心、用户管理、图书分类管理、图书信息管理、图书借阅管理、图书归还管理、图书入库管理、热门图书管理、论坛管理、系统管理&#xff0c;用户&#xff1b;系统首页、个人中心、图书借阅管理、图…

数据科学最佳实践:Kedro 的工程化解决方案 | 开源日报 No.47

leonardomso/33-js-concepts Stars: 58.4k License: MIT 这个项目是一个帮助开发者掌握 JavaScript 概念的资源库。该项目基于 Stephen Curtis 撰写的一篇文章&#xff0c;包含了对 33 个重要 JavaScript 概念全面深入地讲解&#xff0c;并被 GitHub 评为 2018 年最佳开源项目…

【二】spring boot-设计思想

spring boot-设计思想 简介&#xff1a;现在越来越多的人开始分析spring boot源码&#xff0c;拿到项目之后就有点无从下手了&#xff0c;这里介绍一下springboot源码的项目结构 一、项目结构 从上图可以看到&#xff0c;源码分为两个模块&#xff1a; spring-boot-project&a…