Spring Boot 实现多数据源配置

一、配置流程

在 Spring Boot 中实现多数据源配置通常用于需要连接多个数据库的场景。主要有以下几个步骤:

  1. 配置多个数据源的连接信息。
  2. 定义多个数据源的 Bean。
  3. 为每个数据源配置MyBatis的SqlSessionFactory和事务管理器。
  4. 为每个数据源定义Mapper接口和Mapper XML文件。
  5. 在服务类中使用不同的Mapper接口操作对应的数据源。

二、详细步骤

2.1 添加依赖

首先,在pom.xml中添加MyBatis、数据库驱动和Spring Boot的JDBC依赖。

<dependencies><!-- Spring Boot Starter Web (可选,如果需要使用Web功能) --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- MyBatis Starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.2</version></dependency><!-- MySQL 驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- Spring Boot Starter JDBC --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency>
</dependencies>
2.2 配置多数据源

在application.properties或application.yml中配置多个数据源的连接信息。

spring:datasource:primary:jdbc-url: jdbc:mysql://localhost:3306/db1username: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driversecondary:jdbc-url: jdbc:mysql://localhost:3306/db2username: rootpassword: passworddriver-class-name: com.mysql.cj.jdbc.Driver
2.3 配置数据源Bean

在Spring Boot中,通过@Configuration类来配置多个数据源的Bean。

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;import javax.sql.DataSource;@Configuration
public class DataSourceConfig {// 主数据源@Bean(name = "primaryDataSource")@Primary@ConfigurationProperties(prefix = "spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}// 次数据源@Bean(name = "secondaryDataSource")@ConfigurationProperties(prefix = "spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}
}
2.4 配置MyBatis的SqlSessionFactory和事务管理器

为每个数据源配置独立的SqlSessionFactory和DataSourceTransactionManager。

  • PrimaryDataSourceConfig .java

    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;@Configuration
    @MapperScan(basePackages = "com.example.mapper.primary", sqlSessionFactoryRef = 	"primarySqlSessionFactory")
    public class PrimaryDataSourceConfig {@Bean(name = "primarySqlSessionFactory")@Primarypublic SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);// 设置MyBatis的Mapper XML文件路径sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*.xml"));return sessionFactory.getObject();}@Bean(name = "primaryTransactionManager")@Primarypublic DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
    }
    
  • SecondaryDataSourceConfig.java

    import org.apache.ibatis.session.SqlSessionFactory;
    import org.mybatis.spring.SqlSessionFactoryBean;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;@Configuration
    @MapperScan(basePackages = "com.example.mapper.secondary", sqlSessionFactoryRef = "secondarySqlSessionFactory")
    public class SecondaryDataSourceConfig {@Bean(name = "secondarySqlSessionFactory")public SqlSessionFactory secondarySqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();sessionFactory.setDataSource(dataSource);// 设置MyBatis的Mapper XML文件路径sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/secondary/*.xml"));return sessionFactory.getObject();}@Bean(name = "secondaryTransactionManager")public DataSourceTransactionManager secondaryTransactionManager(@Qualifier("secondaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
    }
    
2.5 配置Mapper接口和XML文件

将Mapper接口和XML文件分别放在不同的包中,以区分不同的数据源。

  • 主数据源Mapper接口

    package com.example.mapper.primary;import com.example.model.User;
    import org.apache.ibatis.annotations.Mapper;
    import java.util.List;@Mapper
    public interface PrimaryUserMapper {List<User> findAll();
    }
    
  • 次数据源Mapper接口

    package com.example.mapper.secondary;import com.example.model.Product;
    import org.apache.ibatis.annotations.Mapper;
    import java.util.List;@Mapper
    public interface SecondaryProductMapper {List<Product> findAll();
    }
    
  • 主数据源Mapper XML文件
    在src/main/resources/mapper/primary目录下创建UserMapper.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.mapper.primary.PrimaryUserMapper"><select id="findAll" resultType="com.example.model.User">SELECT * FROM user</select>
    </mapper>
    
  • 次数据源Mapper XML文件
    在src/main/resources/mapper/secondary目录下创建ProductMapper.xml:

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.example.mapper.secondary.SecondaryProductMapper"><select id="findAll" resultType="com.example.model.Product">SELECT * FROM product</select>
    </mapper>
    
2.6 使用多数据源

在Service中注入对应的Mapper接口,并使用@Transactional注解指定事务管理器。

import com.example.mapper.primary.PrimaryUserMapper;
import com.example.mapper.secondary.SecondaryProductMapper;
import com.example.model.User;
import com.example.model.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.List;@Service
public class MyService {@Autowiredprivate PrimaryUserMapper primaryUserMapper;@Autowiredprivate SecondaryProductMapper secondaryProductMapper;@Transactional("primaryTransactionManager")public List<User> getUsers() {return primaryUserMapper.findAll();}@Transactional("secondaryTransactionManager")public List<Product> getProducts() {return secondaryProductMapper.findAll();}
}

三、动态数据源切换

如果需要动态切换数据源,可以通过以下步骤:

  1. 动态数据源配置
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSourceType();}
    }
    
  2. 数据源上下文持有者
    public class DataSourceContextHolder {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public static void setDataSourceType(String dataSourceType) {contextHolder.set(dataSourceType);}public static String getDataSourceType() {return contextHolder.get();}public static void clearDataSourceType() {contextHolder.remove();}
    }
    
  3. AOP切面
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.springframework.stereotype.Component;@Aspect
    @Component
    public class DataSourceAspect {@Before("@annotation(dataSource)")public void switchDataSource(DataSource dataSource) {DataSourceContextHolder.setDataSourceType(dataSource.value());}
    }
    
  4. 自定义注解
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;@Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface DataSource {String value();
    }
    
  5. 使用动态数据源
    @Service
    public class MyService {@DataSource("primary")public List<User> getUsers() {return primaryUserMapper.findAll();}@DataSource("secondary")public List<Product> getProducts() {return secondaryProductMapper.findAll();}
    }
    

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

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

相关文章

p5.js:绘制各种内置的几何体,能旋转

向 豆包 提问&#xff1a;请编写 p5.js 示例&#xff0c; 绘制各种内置的几何体&#xff0c;能让这些几何体缓慢旋转。 cd p5-demo copy .\node_modules\p5\lib\p5.min.js . 此代码创建了一个包含多个内置几何体的 3D 场景&#xff0c;每个几何体都有不同的颜色和位置。运行代…

结构体定义与应用

引言 到今天为止,c语言的基础操作和基础数据类型,就都已经结束了,大家都知道,如果要实现复杂的功能,大家都可以通过函数封装调用,那么如果要实现基础数据类型的封装,该怎么办呢?答案就是结构体。 在C语言编程中,结构体(struct)是非常重要的一个概念,它为程序员提供…

MindGYM:一个用于增强视觉-语言模型推理能力的合成数据集框架,通过生成自挑战问题来提升模型的多跳推理能力。

2025-03-13&#xff0c;由中山大学和阿里巴巴集团的研究团队提出了MindGYM框架&#xff0c;通过合成自挑战问题来增强视觉-语言模型&#xff08;VLMs&#xff09;的推理能力。MindGYM框架通过生成多跳推理问题和结构化课程训练&#xff0c;显著提升了模型在推理深度和广度上的表…

R语言零基础系列教程-01-R语言初识与学习路线

代码、讲义、软件回复【R语言01】获取。 R语言初识 R是一个开放的统计编程环境&#xff0c;是一门用于统计计算和作图的语言。“一切皆是对象”&#xff0c;数据、函数、运算符、环境等等都是对象。易学&#xff0c;代码像伪代码一样简洁&#xff0c;可读性高强大的统计和可视…

PythonWeb开发框架—Flask-APScheduler超详细使用讲解

1.定时任务的两种实现方式 1.1 用scheduler.task装饰任务 安装插件&#xff1a; pip install Flask-APScheduler pip install apscheduler 脚本实现&#xff1a; ###app.py##导入依赖库 from flask import Flask import datetime import config from flask_apscheduler i…

python_巨潮年报pdf下载

目录 前置&#xff1a; 步骤&#xff1a; step one: pip安装必要包&#xff0c;获取年报url列表 step two: 将查看url列表转换为pdf url step three: 多进程下载pdf 前置&#xff1a; 1 了解一些股票的基本面需要看历年年报&#xff0c;在巨潮一个个下载比较费时间&…

从0到1构建AI深度学习视频分析系统--基于YOLO 目标检测的动作序列检查系统:(2)消息队列与消息中间件

文章大纲 原始视频队列Python 内存视频缓存优化方案(4GB 以内)一、核心参数设计二、内存管理实现三、性能优化策略四、内存占用验证五、高级优化技巧六、部署建议检测结果队列YOLO检测结果队列技术方案一、技术选型矩阵二、核心实现代码三、性能优化策略四、可视化方案对比五…

React Native 如何使用 Expo 快速开发?

React Native是当下热门的跨平台移动开发框架&#xff0c;而Expo则是它的重要开发工具之一。Expo提供了一套完整的开发环境&#xff0c;使开发者无需安装Android Studio或Xcode也能快速运行React Native项目。它包含了众多内置API&#xff0c;如相机、地理位置、推送通知等&…

中考英语之09从句

1 宾语从句 定义 在主从复合句中充当宾语&#xff0c;位于及物动词、介词或复合谓语之后的从句。 引导词 综述&#xff1a; that&#xff08;可省略&#xff09;、if/whether、连接代词&#xff08;what、which、who、whom、whose 等&#xff09;和连接副词&#xff08;when、…

平方矩阵问题

Ⅰ 回字形二维数组 #include <iostream> #include <iomanip> using namespace std; int main(){int n;while(cin>>n,n){for(int i0; i<n;i){for(int j0; j<n; j){int upi, downn-i1, leftj, rightn-j1;cout<<min(min(up,down),min(left,right)…

C++模版(复习)

1.泛型编程&#xff1a;编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础 2.函数模板的格式 template<typename T1,typename T2,…,typename Tn> 返回类型 函数名(参数列表) {   //函数体 } 3.template<class T1,class T2,…,class…

【sklearn 05】sklearn功能模块

sklearn功能模块 分类&#xff1a;识别某个对象属于那个类别回归&#xff1a;预测与对象相关联的连续值属性聚类&#xff1a;将相似对象自动分组降维&#xff1a;减少要考虑的随机变量的数量模型选择&#xff1a;比较、验证、选择参数和模型预处理&#xff1a;特征提取和归一化…

使用Qt创建悬浮窗口

在Qt中创建悬浮窗口&#xff08;如无边框、可拖动的浮动面板或提示框&#xff09;可以通过以下方法实现。以下是几种常见场景的解决方案&#xff1a; 方法1&#xff1a;使用无边框窗口 鼠标事件拖动 适用于自定义浮动工具窗口&#xff08;如Photoshop的工具栏&#xff09;。 …

《P4387 【深基15.习9】验证栈序列》

题目描述 给出两个序列 pushed 和 poped 两个序列&#xff0c;其取值从 1 到 n(n≤100000)。已知入栈序列是 pushed&#xff0c;如果出栈序列有可能是 poped&#xff0c;则输出 Yes&#xff0c;否则输出 No。为了防止骗分&#xff0c;每个测试点有多组数据&#xff0c;不超过 …

校园安全用电怎么保障?防触电装置来帮您

引言 随着教育设施的不断升级和校园用电需求的日益增长&#xff0c;校园电力系统的安全性和可靠性成为了学校管理的重要课题。三相智能安全配电装置作为一种电力管理设备&#xff0c;其在校园中的应用不仅能够提高电力系统的安全性&#xff0c;还能有效保障师生的用电安全&am…

【Git】--- 初识Git Git基本操作

Welcome to 9ilks Code World (๑•́ ₃ •̀๑) 个人主页: 9ilk (๑•́ ₃ •̀๑) 文章专栏&#xff1a; Git 本篇我们来初步认识Git企业级应用是什么&#xff0c;有什么用以及Git基本操作。 &#x1f3e0; 初始Git 提出问题 在日常生活中&#xff0c;我们进行…

数据治理下半场:如何用文化变革撬动企业数字化转型?

数据治理下半场:如何用文化变革撬动企业数字化转型? 一、打破认知茧房:从"数据恐惧症"到"数据生产力"二、重构协作生态:从"部门墙"到"数据共同体"三、建立责任体系:从"无人认领"到"终身责任制"​四、点燃创新…

Chat-Driven Business:灵活交互的新范式

1. 引言 一次偶然的机会&#xff0c;读到了CSDN上的一篇文章&#xff0c;自定义markdown的展示(很遗憾&#xff0c;时间有点久&#xff0c;找不到具体的链接了&#xff09;&#xff0c;当时我觉得这很有启发意义&#xff0c;因为我做的cli_assistant就是以markdown的形式返回的…

嵌入式裸机设计--MCU常用裸机架构有哪些?

为什么是裸机设计 792125321入群学习更高效&#xff01; 在MCU&#xff08;微控制器单元&#xff09;裸机开发中&#xff0c;我们常见的架构设计主要围绕如何高效管理资源和任务调度。认识这些开发方式&#xff0c;对我们开发一个小型项目来说及有好处&#xff01; 下面介绍…

python内置函数sum的用法

知识点 - sum 函数 基本语法 sum(iterable[, start]) iterable 是一个可迭代对象&#xff0c;例如列表、元组、集合等&#xff0c;其中的元素通常是数字类型&#xff08;整数或浮点数&#xff09;。 start 是一个可选参数&#xff0c;表示累加的起始值&#xff0c;默认为 0。…