【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置

news2025/4/19 7:37:30

前言

大多数 Spring 应用程序只有一个数据源,只需要一个事务管理器(TransactionManager)。
但是在多个数据源的情况下,我们就需要在一个应用程序中配置多个独立的事务管理器。
我们可以通过 @Transactional 的 value 或 transactionManager 属性来指定让哪个 TransactionManager 生效。

https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#tx-multiple-tx-mgrs-with-attransactional

那么,一个数据源 与 多数据源的事物管理配置有什么不同呢?

正文

事物管理相关的几个核心概念有:DataSource、TransactionManager 和 TransactionInterceptor。

  • DataSource
    DataSource 是用来获取 DB 连接的。

  • TransactionManager
    用来管理事物,核心的接口有 PlatformTransactionManager,它可以获取连接、提交/回滚事物。

  • TransactionInterceptor
    它是 spring-tx 用来实现声明式事物管理的核心类,它会对事物方法进行拦截,然后实现事物的操作(提交/回滚事物)。

所以,我们在进行 spring 的事物管理配置的时候,这三个重要的角色都需要参与进来:DataSource、TransactionManager 和 TransactionInterceptor。

单个数据源的事物管理配置

可能你会说 Spring 开启事物管理不就是使用一个 @EnableTransactionManagement 就搞定了吗?确实也是这样。
仔细想想,我们不禁会有疑问:
1、@EnableTransactionManagement 能开启事物管理的原理是什么呢?
2、如果没有 @EnableTransactionManagement,我们自己配置事物管理的话,应当如何配置呢?

手动进行事物管理配置

我们先来看一下,如果没有使用 @EnableTransactionManagement 的情况下,应该如何来进行事物管理的配置?

如果使用 MyBatis 来操作数据库的话,手动进行事物管理的配置可以分为四个步骤进行:

  • 1、定义数据源 DataSource
  • 2、定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、定义 Advisor 来拦截 @Transactional 方法(主要是让 Advice:TransactionInterceptor 生效)
  • 4、定义基于 DataSource 的 SqlSessionFactory(通过 MyBatis 来操作 sql)

例如:

@Configuration
@MapperScan(basePackages = "com.kvn.mapper.biz", sqlSessionFactoryRef = "bizSqlSessionFactory")
public class MasterMybatisConfig {

    @Bean("biz")
    @ConfigurationProperties(prefix = "spring.datasource.biz")
    public DataSource bizDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 创建 biz 数据源的事物管理器
     */
    @Bean(name = "bizTxManager")
    public PlatformTransactionManager bizTxManager(@Qualifier("biz") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("bizSqlSessionFactory")
    public SqlSessionFactory bizSqlSessionFactory(@Qualifier("biz") DataSource dataSource) throws Exception {
      // 设置数据源
      SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
      sqlSessionFactoryBean.setDataSource(dataSource);
      //mapper的xml文件位置
      PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
      String locationPattern = "classpath*:/mapper/biz/*.xml";
      sqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
      //对应数据库的entity位置
      String typeAliasesPackage = "com.kvn.entity.biz";
      sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
      return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      TransactionAttributeSource transactionAttributeSource = new AnnotationTransactionAttributeSource();
      interceptor.setTransactionAttributeSource(transactionAttributeSource);
      
      // 定义 Advisor --> Pointcut + Advice
      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource); // 供 Pointcut 使用
      advisor.setAdvice(interceptor); // Advice  
      return advisor;
    }
}

注意:如果我们不需要对数据源进行事物管理的话,可以不配置 transactionAdvisor

@EnableTransactionManagement 开启事物管理的原理

在一个只有一个数据源的 SpringBoot 工程中,我们只需要配置一个 @EnableTransactionManagement 就能开启事物管理,让 @Transactional 生效,这是为什么呢?
使用 @EnableTransactionManagement 之后,SpringBoot 为我们配置哪些 bean 来支持事物管理呢?

@EnableTransactionManagement 的作用

查看 @EnableTransactionManagement 的源码,我们可以发现它帮我们注册了 BeanFactoryTransactionAttributeSourceAdvisor,也就是让 TransactionInterceptor 来拦截 @Transactional 标记的方法
但是 @EnableTransactionManagement 并没有帮我们注册 TransactionManagerDataSource

那么,TransactionManagerDataSource 是如何自动注册的呢?
SpringBoot 会帮我们默认注册一个 HikariDataSource
DataSourceConfiguration.png

当只有一个 DataSource 时,SpringBoot 会默认帮我们注册一个 TransactionManager
DataSourceTransactionManagerAutoConfiguration2.png

可以看到,如果我们的工程中只有一个数据源的话,SpringBoot 就会帮我们自动注册一个 TransactionManagerHikariDataSource

@EnableTransactionManagement 的作用是负责注册必要的 Spring 组件,比如:BeanFactoryTransactionAttributeSourceAdvisorTransactionInterceptor,这些组件为注释驱动的事务管理提供了动力和支持。

  • BeanFactoryTransactionAttributeSourceAdvisor
    BeanFactoryTransactionAttributeSourceAdvisor 实现了 PointcutAdvisor 接口,它持有的 Pointcut 决定了匹配 @Transactional 注解标记的方法;
    它持有的 Advice,即 TransactionInterceptor,实现了具体的事物拦截逻辑。
  • TransactionInterceptor
    TransactionInterceptor 在做事物方法拦截时,会去决定使用哪个 TransactionManager,即 TransactionAspectSupport.determineTransactionManager() 方法实现的功能。

多个数据源的事物管理配置

从上面对单个数据源的事物管理配置的研究,我们可以发现 @EnableTransactionManagement 的作用就是帮我们自动注册 BeanFactoryTransactionAttributeSourceAdvisor 来支持对 @Transactoinal 方法的拦截。
TransactionManagerDataSource 是需要另外进行配置的。当工程中只有一个数据源的情况下,SpringBoot 又会默认帮我们注册 TransactionManagerDataSource ,所以,在只有一个数据源的情况下,我们通过 @EnableTransactionManagement 注解就能顺利的通过 spring-tx 来管理事物。

当工程中有多个数据源的时候(>=2),我们依然可以通过 @EnableTransactionManagement 来自动注册 BeanFactoryTransactionAttributeSourceAdvisor,但是 SpringBoot 就不会自动注册 TransactionManagerDataSource 了,而需要我们手动进行配置。

所以,配置 n 个数据源的事物管理的步骤如下:
1、通过 @EnableTransactionManagement 来开启对 @Transactional 方法的拦截
2、定义 n 个数据源 DataSource
3、定义基于 DataSource 的 TransactionManager(事物管理器)
4、定义基于 DataSource 的 SqlSessionFactory (通过 MyBatis 操作 sql)

手动配置 2 个数据源的例子:

  • 定义 master 数据源 & 事物管理器
    masterDataSource.png

  • 定义 slave 数据源 & 事物管理器
    slaveDataSource.png

  • 数据源的 properties 配置
    dataSourceProperties.png

注意:多数据源的情况下,需要使用类似 @Transactional("masterTxManager") 来指定事物方法使用的事物管理器是哪个。

小结

配置 spring 的事物管理,大体分为三个步骤:(单数据源 与 多数据源 都是如此)

  • 1、定义数据源 DataSource
  • 2、定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、定义 Advisor 来拦截 @Transactional 方法(主要是让 Advice:TransactionInterceptor 生效)

不管是一个数据源,还是多个数据源,都是上面的套路。
一个数据源的配置 与 多个数据源的配置 的不同是:如果工程中只需要一个数据源,那么 SpringBoot 可以为我们做到全自动的配置,只需要使用 @EnableTransactionManagement 就可以使用 spring 的事物管理。


SpringBoot 能自动配置单个数据源的事物管理的原理是:
1、spring-boot-autoconfigure.jar 中的 DataSourcePoolMetadataProvidersConfiguration 类会帮我们自动注册 HikariDataSource
2、spring-boot-autoconfigure.jar 中的 DataSourceTransactionManagerAutoConfiguration 类会帮我们自动注册 TransactionManager
3、@EnableTransactionManagement 会注册 Advisor: BeanFactoryTransactionAttributeSourceAdvisor

如果是多数据源进行事物管理配置的话,步骤如下:

  • 1、手动定义 n 个 DataSource
  • 2、手动定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、添加 @EnableTransactionManagement 来开启对 @Transactional 方法的拦截

系统的学习源码知识,请点击视频讲解:
SpringIoC源码由浅入深 : https://edu.51cto.com/course/30243.html


点赞、收藏、关注不迷路…⇩↓☟⬇︎⥥…
gzh_b2.png

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

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

相关文章

shell数值计算

P23 回顾shell基础知识 shell执行多条命令 一行内,分号分割多条命令。比如cd /tmp ;echo hello ;cd - 其中cd -为回到此行命令开始前的目录多行echo和转义字符 双引号里输出$n等特殊字符时,实用\转义,来原样输出字符单引号中字符不进行替换&…

ES6的简单使用

1.ES6基本介绍1996 年 11 月,JavaScript 的创造者 Netscape 公司,决定将 JavaScript 提交给标准化组织 ECMA,希望这种语言能够成为国际标准。次年,ECMA 发布 262 号标准文件(ECMA-262)的第一版,…

Vue表单数据修改与删除

学习来源:视频p6 书接上文 目录页面修改修改对话框视频教程的做法后端提供接口前端调用接口修改完成后提交删除功能后端开设接口前端调用最终成果展示页面修改 将之前的 BookManage 页面的按钮改为想要的功能 可以注意到修改按钮的标签以及绑定了事件 handleClick…

RK3568核心板以太网大数据测试报告-万象奥科

1. 测试对象HD-RK3568-IOT 底板基于HD-RK3568-CORE工业级核心板设计(双网口、双CAN、5路串口),接口丰富,适用于工业现场应用需求,亦方便用户评估核心板及CPU的性能。适用于工业自动化控制、人机界面、中小型医疗分析器…

docker环境下docker-compose一键式搭建fastdfs文件存储服务系统

前言 本节内容我们使用docker-compose一键式搭建一套fastdfs服务,实现docker环境下的文件存储服务,在开始本节内容之前,我们需要提前安装好docker和docker-compose环境。fastdfs是一套分布式的文件存储服务系统,主要有tracker和s…

pipenv的基本使用

一. pipenv 基础 pipenv安装: pip install pipenvpipenv常用命令 pipenv --python 3 # 创建python3虚拟环境 pipenv --venv # 查看创建的虚拟环境 pipenv install 包名 # 安装包 pipenv shell # 切换到虚拟环境中 pip list # 查看当前已经安装的包&#xff0…

地方征信平台第2讲:河北省征信

河北省征信有限公司,注册成立于2022年12月25日,注册资本6330万元人民币。股东及持股比例如下:河北省惠信大数据科技服务有限公司、35.1975%。唐山国控集团有限公司、14.22%。石家庄城控投资集团有限责任公司、 10.8215%。石家庄市国有资本经营…

【017】筛选数据并整理(筛选、返回行号、清除全部数据)_#VBA

自动化办公1. 筛选1.1 在某一基础上筛选1.2 多条件筛选2. 返回行号3. 删除某列重复数据4. 删除当页全部数据5. 求和6. 复制黏贴6.1 第一种6.2 第二种6.2 第三种7. 全部数据1. 筛选 主要使用的命名方式如下 ActiveSheet.Range("$A$1:$L$41500").AutoFilter Field:1,…

打电话哪款蓝牙耳机好?打电话好的蓝牙耳机推荐

耳机除了听歌之外,还经常会用到接听电话。很多真正的无线耳机,在宣传页面上,都会着重介绍自己的耳机在降噪、音质方面的性能,以及他们自己的耳机的性能,下面分享几款打电话好的蓝牙耳机。 一、南卡小音舱蓝牙耳机 蓝…

人机交互设计概述

人机交互的软件工程实践 1.人机交互设计概述 交互设计视图提高产品或系统的可用性和用户体验。他首先研究、了解某类用户的需求,然后再通过设计来满足用户的需求。随着产品和操作变得越来越复杂,越需要用户掌握新技能,因此设计师对如何能帮…

密码学基础(一)常见密码算法分类

一、密码算法分类: 密码算法主要分为三类:对称密码算法、 非对称密码算法、摘要算法。 二、对称密码算法(Symmetric-key Algorithm) 1、概念 对称加密(也叫私钥加密)指加密和解密使用相同密钥的加密算法。有时又叫传统密码算…

8Manage PMO:如何借助系统软件解决多项目管理难点

随着企业不断发展壮大,大多数企业不管性质、规模和行业如何,都会同时进行多个项目,这已然成为一个普遍现象。虽然多项目管理可以提高资源利用率,加速项目交付,但同时也会带来一系列的难点。 如何在多个项目之间有效地…

Python基于词频排序快速挖掘需求大类

Python基于词频排序快速挖掘需求大类 作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 一、所有的代码 这是所有的代码 from collections import defaultdict import jieba.posseg a…

华为机试题:HJ101 输入整型数组和排序标识,对其元素按照升序或降序进行排序(python)

文章目录(1)题目描述(2)Python3实现(3)知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方…

数字信息-数字编码挂钩法

一、前方无路,一切才刚开始0呼啦圈 1蜡烛2鹅 3金元宝4青龙5钩子6哨子 7七仙女8八卦镜9药酒二、少年中国说看到“1”想到“树”,想到“树”,想到“智慧树”,再想到“少年智则国智”看到“2”想到“鸭子”,想到“鸭子”&…

基于 centos7 搭建 laravel+scout+elasticsearch+ik-analyzer 用于中文分词全文检索服务及测试

目录基于 centos7 搭建 laravelscoutelasticsearchik-analyzer 用于中文分词全文检索服务及测试相关软件及版本安装或升级jdk(版本:19.0.2)安装es(版本:8.1.1)安装ik-analyzer(版本:…

transformer目标检测开山之作detr

1. 将一个batch的图片输入backone获得feature。 (2,c,w,h)先输入resnet50中,得到(2,2048,w,h)。虽然这里channel不是256,但是在输入e…

pg mysql oracle 中的schema

1、schema。 pg中的schema表示当前db中数据库对象的命名空间(namespace),数据库对象包括但不限于表、函数、视图、索引等。 对于熟悉mysql的人来说,在第一次看到pg中的schema的概念时,可能会疑惑,schema不是表示database的吗&…

如何使用码匠连接 Elasticsearch

目录 在码匠中集成 Elasticsearch 在码匠中使用 Elasticsearch 关于码匠 Elasticsearch 是一个开源的分布式搜索和分析引擎,常用于处理大规模数据集的搜索、实时数据分析和数据挖掘任务。它支持多种数据源,包括关系型数据库(如 MySQL、Pos…

不想重写Dockerfile如何更改docker容器的挂载目录

一、问题 从网络上下载的很多Dockerfile或docker-compose文件进行启动容器的时候,部分重要的目录是依赖volumes挂载到容器内部的,如图 这就会出现一个问题,当我们想将容器打包,便于以后使用的时候,这部分挂载的文件是…