springboot实现多数据源

前言:Spring Boot提供了简单而强大的多数据源支持,使得在应用程序中轻松使用和管理多个数据库变得非常容易。使用多数据源可以解决一些复杂的业务场景,比如在一个应用中同时访问多个数据库,或者在微服务架构中需要每个微服务连接自己的数据库。

在Spring Boot和MyBatis中实现多数据源可以通过配置多个数据源和事务管理器来实现。以下是一个简单的步骤:

1、添加依赖:确保在pom.xml文件中添加Spring Boot和MyBatis的相关依赖。

例如: 

<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MyBatis --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
</dependencies>

2、配置数据源

application.properties(或application.yml)文件中配置多个数据源信息。

例如:

# 第一个数据源
spring.datasource.first.url=jdbc:mysql://localhost:3306/first_db
spring.datasource.first.username=username1
spring.datasource.first.password=password1
spring.datasource.first.driver-class-name=com.mysql.cj.jdbc.Driver# 第二个数据源
spring.datasource.second.url=jdbc:mysql://localhost:3306/second_db
spring.datasource.second.username=username2
spring.datasource.second.password=password2
spring.datasource.second.driver-class-name=com.mysql.cj.jdbc.Driver

3、配置数据源Bean

import com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;/*** 配置连接*/
@Configuration
@MapperScan(basePackages = "com.smoky.dao" ,sqlSessionTemplateRef = "sqlSessionTemplateA"
)
public class MyBatisConfig {private Logger logger = LoggerFactory.getLogger(MyBatisConfig.class);@Value("${spring.datasource.datasourceA.driver-class-name}")private String driverClassNameA;@Bean(name = "dataSourceA")@Primary@ConfigurationProperties(prefix = "spring.datasource.datasourceA")public DataSource dataSourceA() {return DataSourceBuilder.create().build();}@Primary@Bean(name = "sqlSessionFactoryA")public SqlSessionFactory testSqlSessionFactoryA(@Qualifier("dataSourceA") DataSource dataSource) throws Exception {ResourcePatternResolver patternResolver = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());SqlSessionFactoryBean sqlSession = new CDBSqlSessionFactoryBean();sqlSession.setDataSource(dataSource);String classPath;if ("com.mysql.cj.jdbc.Driver".equals(driverClassNameA)) {classPath = "classpath*:mysql_mapper/*.xml";} else if ("oracle.jdbc.driver.OracleDriver".equals(driverClassNameA)) {classPath = "classpath*:oracel_mapper/*.xml";} else if ("com.ibm.db2.jcc.DB2Driver".equals(driverClassNameA)) {classPath = "classpath*:db2_mapper/*.xml";} else {throw new SystemException(SystemErrorEnum.SYSTEM_ERROR.getCode(), "不支持的数据库类型");}//根据实际情况添加,视情况删除sqlSession.setVfs(SpringBootVFS.class);org.apache.ibatis.session.Configuration conf = new org.apache.ibatis.session.Configuration();// 查询结果为map时不忽略空值conf.setCallSettersOnNulls(true);// 开启驼峰命名转换 conf.setMapUnderscoreToCamelCase(true);sqlSession.setConfiguration(conf);try {sqlSession.setMapperLocations(patternResolver.getResources(classPath));} catch (Exception e) {logger.error(e.getMessage());}return sqlSession.getObject();}@Primary@Bean(name = "transactionManagerA")public DataSourceTransactionManager testTransactionManagerA(@Qualifier("dataSourceA") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Primary@Bean(name = "sqlSessionTemplateA")public SqlSessionTemplate testSqlSessionTemplateA(@Qualifier("sqlSessionFactoryA") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}}

 

import com.baomidou.mybatisplus.spring.boot.starter.SpringBootVFS;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;import javax.sql.DataSource;/*** 配置连接*/
@Configuration
@MapperScan(basePackages = "com.smoky.skdao" ,sqlSessionTemplateRef = "sqlSessionTemplateB"
)public class SKMybatisConfig {private Logger logger = LoggerFactory.getLogger(SKMybatisConfig.class);@Value("${spring.datasource.datasourceB.driver-class-name}")private String driverClassNameB;@Bean(name = "dataSourceB")@ConfigurationProperties(prefix = "spring.datasource.datasourceB")public DataSource dataSourceB() {return DataSourceBuilder.create().build();}@Bean(name = "sqlSessionFactoryB")public SqlSessionFactory testSqlSessionFactoryB(@Qualifier("dataSourceB") DataSource dataSource) throws Exception {ResourcePatternResolver patternResolver = ResourcePatternUtils.getResourcePatternResolver(new DefaultResourceLoader());SqlSessionFactoryBean sqlSession = new CDBSqlSessionFactoryBean();sqlSession.setDataSource(dataSource);String classPath;if ("com.mysql.cj.jdbc.Driver".equals(driverClassNameB)) {classPath = "classpath*:sk_mysql_mapper/*.xml";} else if ("oracle.jdbc.driver.OracleDriver".equals(driverClassNameB)) {classPath = "classpath*:oracel_mapper/*.xml";} else if ("com.ibm.db2.jcc.DB2Driver".equals(driverClassNameB)) {classPath = "classpath*:db2_mapper/*.xml";} else {throw new SystemException(SystemErrorEnum.SYSTEM_ERROR.getCode(), "不支持的数据库类型");}//根据实际情况添加,视情况删除sqlSession.setVfs(SpringBootVFS.class);org.apache.ibatis.session.Configuration conf = new org.apache.ibatis.session.Configuration();// 查询结果为map时不忽略空值conf.setCallSettersOnNulls(true);// 开启驼峰命名转换   seckill_id====>seckillIdconf.setMapUnderscoreToCamelCase(true);sqlSession.setConfiguration(conf);try {sqlSession.setMapperLocations(patternResolver.getResources(classPath));} catch (Exception e) {logger.error(e.getMessage());}return sqlSession.getObject();}@Bean(name = "transactionManagerB")public DataSourceTransactionManager testTransactionManagerB(@Qualifier("dataSourceB") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}@Bean(name = "sqlSessionTemplateB")public SqlSessionTemplate testSqlSessionTemplateB(@Qualifier("sqlSessionFactoryB") SqlSessionFactory sqlSessionFactory) throws Exception {return new SqlSessionTemplate(sqlSessionFactory);}}

4、使用多数据源,首先,创建主数据源的UserMapper接口:

package com.example.mapper.primary;import com.example.model.User;import java.util.List;public interface UserMapper {User getUserById(Long id);List<User> getAllUsers();void insertUser(User user);void updateUser(User user);void deleteUser(Long id);
}

主数据源Mapper XML文件

src/main/resources/mapper/primary目录下,创建主数据源的UserMapper.xml文件:

<!-- src/main/resources/mapper/primary/UserMapper.xml --><mapper namespace="com.example.mapper.primary.UserMapper"><!-- 根据ID查询用户 --><select id="getUserById" resultType="com.example.model.User">SELECT * FROM users_primary WHERE id = #{id}</select><!-- 查询所有用户 --><select id="getAllUsers" resultType="com.example.model.User">SELECT * FROM users_primary</select><!-- 插入用户 --><insert id="insertUser" parameterType="com.example.model.User">INSERT INTO users_primary (username, email) VALUES (#{username}, #{email})</insert><!-- 更新用户 --><update id="updateUser" parameterType="com.example.model.User">UPDATE users_primary SET username = #{username}, email = #{email} WHERE id = #{id}</update><!-- 根据ID删除用户 --><delete id="deleteUser">DELETE FROM users_primary WHERE id = #{id}</delete></mapper>

第二数据源Mapper接口:接着,创建第二数据源的UserMapper接口:

package com.example.mapper.secondary;import com.example.model.User;import java.util.List;public interface UserMapper {User getUserById(Long id);List<User> getAllUsers();void insertUser(User user);void updateUser(User user);void deleteUser(Long id);
}

第二数据源Mapper XML文件:在src/main/resources/mapper/secondary目录下,创建第二数据源的UserMapper.xml文件:

<!-- src/main/resources/mapper/secondary/UserMapper.xml --><mapper namespace="com.example.mapper.secondary.UserMapper"><!-- 根据ID查询用户 --><select id="getUserById" resultType="com.example.model.User">SELECT * FROM users_secondary WHERE id = #{id}</select><!-- 查询所有用户 --><select id="getAllUsers" resultType="com.example.model.User">SELECT * FROM users_secondary</select><!-- 插入用户 --><insert id="insertUser" parameterType="com.example.model.User">INSERT INTO users_secondary (username, email) VALUES (#{username}, #{email})</insert><!-- 更新用户 --><update id="updateUser" parameterType="com.example.model.User">UPDATE users_secondary SET username = #{username}, email = #{email} WHERE id = #{id}</update><!-- 根据ID删除用户 --><delete id="deleteUser">DELETE FROM users_secondary WHERE id = #{id}</delete></mapper>

使用Mapper接口:在需要使用数据访问的地方,注入对应的UserMapper接口,然后调用接口中定义的方法:

@Service
public class UserService {private final UserMapper primaryUserMapper;private final UserMapper secondaryUserMapper;@Autowiredpublic UserService(@Qualifier("primaryUserMapper") UserMapper primaryUserMapper,@Qualifier("secondaryUserMapper") UserMapper secondaryUserMapper) {this.primaryUserMapper = primaryUserMapper;this.secondaryUserMapper = secondaryUserMapper;}public User getPrimaryUserById(Long id) {return primaryUserMapper.getUserById(id);}public User getSecondaryUserById(Long id) {return secondaryUserMapper.getUserById(id);}// 其他业务方法...
}

 在这个示例中,UserMapper接口和XML文件分别针对主数据源和第二数据源进行了定义和配置。在UserService中,通过@Qualifier注解分别注入了主数据源和第二数据源的UserMapper,使得在业务层可以方便地调用对应数据源的方法。需要确保主数据源和第二数据源的配置和连接信息都正确,以便MyBatis能够正确地访问数据库。

 总结:

在Spring Boot应用程序中利用MyBatis实现多数据源的配置。这一技术的重要性在于,对于复杂的应用场景,如微服务架构或需要同时连接多个数据库的系统,多数据源的支持成为了必备的功能。通过以下几个关键步骤,我们成功地搭建了一个支持多数据源的Spring Boot应用:

首先,我们在pom.xml文件中引入了Spring Boot、MyBatis以及相应的数据库驱动依赖,确保项目能够充分利用这些强大的框架。

其次,通过在application.properties中配置多个数据源的连接信息,我们为每个数据库建立了必要的基础设置。这包括数据库的URL、用户名、密码等信息。

接下来,我们创建了DataSourceConfig类,通过该类配置了每个数据源的DataSource Bean。这一步骤对于确保数据源的正确配置至关重要。

在MyBatis的配置方面,我们使用了SqlSessionFactorySqlSessionTemplate,并通过@MapperScan注解指定了Mapper接口的扫描路径。这样,MyBatis能够正确地找到和关联到各个数据源的Mapper接口和XML文件。

最后,为了实现事务管理,我们创建了TransactionManagerConfig类,为每个数据源配置了对应的事务管理器。这确保了在多数据源的环境下,事务能够得到正确的管理和隔离。

通过以上步骤的完成,我们不仅成功实现了多数据源的配置,而且在MyBatis的Mapper接口和XML文件中清晰地定义了数据库操作。这种模块化的数据访问层设计使得代码更易维护、更具可读性。总的来说,本文提供了一个全面而实用的指南,帮助开发者们在Spring Boot应用中优雅地处理多数据源的场景,充分发挥了Spring Boot和MyBatis的优势,提高了应用的灵活性和可扩展性。

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

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

相关文章

Python电能质量扰动信号分类(四)基于CNN-BiLSTM的一维信号分类模型

往期精彩内容&#xff1a; 引言 1 数据集制作与加载 1.1 导入数据 1.2 制作数据集 2 CNN-BiLSTM分类模型和超参数选取 2.1定义CNN-BiLSTM分类模型 2.2 设置参数&#xff0c;训练模型 3 模型评估 3.1 准确率、精确率、召回率、F1 Score 3.2 十分类混淆矩阵&#xff1a…

28、商城系统(十):ElasticSearch的映射,nginx下载安装,es分词器,springboot整合es

目录 一、Mapping映射 1.es7删除类型 2.es给字段设置字段类型,即映射 (1)创建映射

C++多态性——(3)动态联编的实现——虚函数

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 成功的秘诀就在于多努力一次&#xff…

gookit/color - Go语言命令行色彩使用库教程

gookit/color - Go语言命令行色彩使用库教程 1.安装2.基础颜色(16-color)3.256色彩/RGB风格 1.安装 go get github.com/gookit/color2.基础颜色(16-color) 提供通用的API方法&#xff1a;Print Printf Println Sprint Sprintf 1、例如&#xff1a; color.Yellow.Println(&q…

Python:单下划线 双下划线

本文参考&#xff1a;https://machinelearning.blog.csdn.net/article/details/125114737 单下划线 1. 变量&#xff08;临时变量&#xff0c;引入未使用的变量&#xff09; 在Python中&#xff0c;变量包含&#xff1a;数字、字母、下划线等&#xff1b;所以单独一个下划线_…

Kotlin 密封类与接口

密封的类和接口表示受限制的类层次结构&#xff0c;这些层次结构提供了对继承的更多控制&#xff1b;在定义密封类的模块和包之外&#xff0c;不能出现其他子类&#xff1b;密封类的每个实例都有一个来自有限集的类型&#xff0c;该类型在编译此类时是已知的&#xff1b;一旦编…

Jenkins 构建前端服务更新控制

在当今的快节奏开发环境中&#xff0c;确保前端服务的高效和可靠更新至关重要。本文将介绍如何通过AWS服务&#xff08;如ECS和S3&#xff09;以及Jenkins进行参数化构建&#xff0c;实现前端服务的自动化部署和更新控制。我们将深入了解使用Python脚本管理部署流程&#xff0c…

嵌入式系统(二)单片机基础 | 单片机特点 内部结构 最小系统 电源 晶振 复位

上一篇文章我们介绍了嵌入式系统 嵌入式系统&#xff08;Embedded System&#xff09;是一种特定用途的计算机系统&#xff0c;它通常嵌入在更大的产品或系统中&#xff0c;用于控制、监测或执行特定的任务。这些系统通常由硬件和软件组成&#xff0c;旨在满足特定的需求&…

echarts条纹进度条

drawmonthqualified(){this.monthqualified echarts.init(document.getElementById(monthqualified));this.monthqualified.setOption({grid: {top: "15%",left:"20%",right:20%,bottom: "0%" //也可设置left和right设置距离来控制图表的大小},…

【致远OA】获取指定人员的协同待发列表

接口请求说明 V6.0接口更新:不在传入ticket&#xff0c;改为传memberId人员ID V6.0之前http请求方式&#xff1a;GET http://ip:port/seeyon/rest/affairs/draft 如 http://127.0.0.1/seeyon/rest/affairs/draft?ticketxxxxxx V6.0http请求方式&#xff1a;GET http://ip:p…

SpringBoot中WebSokcet无法注入Bean对象的解决方案

一、业务场景 Slf4j Component ServerEndpoint("/ws/{userId}") public class WebSocketServer {Autowiredprivate IChatService chatService;public static Map<Long, Session> sessionMap new ConcurrentHashMap<>();OnOpenpublic void onOpen(Sessi…

常见网络协议

1.DNS协议 &#xff08;域名系统&#xff09; DNS协议使用的端口号是53 位于OSI模型中的应用层 DNS系统的作用&#xff1a;将域名&#xff08;网址&#xff09;解析为IP地址。 DNS的基本原理是&#xff1a;将域名映射到IP地址 DNS工作流程 当用户给定一个域名&#xff0…

物联网技术如何影响我们的生活

随着科技的不断进步&#xff0c;物联网技术已经深刻地融入了我们的日常生活。物联网&#xff0c;即物联网&#xff08;Internet of Things&#xff0c;IoT&#xff09;&#xff0c;指的是通过互联网连接各种物理设备和对象&#xff0c;使它们能够进行数据交换和实时通信。这项技…

【十三】【动态规划】1745. 分割回文串 IV、132. 分割回文串 II、516. 最长回文子序列,三道题目深度解析

动态规划 动态规划就像是解决问题的一种策略&#xff0c;它可以帮助我们更高效地找到问题的解决方案。这个策略的核心思想就是将问题分解为一系列的小问题&#xff0c;并将每个小问题的解保存起来。这样&#xff0c;当我们需要解决原始问题的时候&#xff0c;我们就可以直接利…

移动端APP版本治理

1、背景 在许多公司&#xff0c;APP版本都是不受重视的&#xff0c;产品忙着借鉴&#xff0c;开发埋头编码&#xff0c;测试想着不粘锅。 只有在用户反馈app不能用的时候&#xff0c;你回复客服说&#xff0c;让用户升级最新版本&#xff0c;是不是很真实。 而且业界也很少有…

一文讲清数据资产入表实操

《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》已发布一年&#xff0c;数据资产化和入表已成为2023年的热门话题&#xff0c;随着2023年底国家数据局吹风《"数据要素x"三年行动计划&#xff08;2024-2026年&#xff09;》即将发布&#xff0c;这…

开发环境 目录记录

2023.12.27 jdk17 位置在 C:\DevelopTools\JavaDevelopTools\jdk17,配置了JAVA_HOME到环境变量&#xff0c;JAVA_HOME\bin到PATHapache-maven-3.6.1 位置在 C:\DevelopTools\JavaDevelopTools\apache-maven-3.6.1,配置了MAVEN_HOME到环境变量&#xff0c;MAVEN_HOME\bin到PA…

周赛378(中心扩散法、分组循环)

文章目录 周赛378[2980. 检查按位或是否存在尾随零](https://leetcode.cn/problems/check-if-bitwise-or-has-trailing-zeros/)转换题意 [2981. 找出出现至少三次的最长特殊子字符串 I](https://leetcode.cn/problems/find-longest-special-substring-that-occurs-thrice-i/)中…

[情商-7]:如何回答没有标准答案的两难问题

目录 前言&#xff1a; 一、用“逻辑推理思维”回答两难问题 二、用“情绪思维”回答两难问题 1.1 关注提问者提出问题背后的情绪状态和情绪/情感诉求 1.2 常见的常见的情绪和情感诉求 1.3 女性情感分析 1.4 理解女性情感的语言 1.5 如何通过语言理解女性的情绪需求 三…

模拟Spring事件监听机制

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 之前我们一起学习了Spr…