SpringBoot集成Mybatis实现对多数据源的访问的“秘密”
思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。 作者:毅航😜
本文主要分析讨论在SpringBoot
应用中我们该如何配置SqlSessionFactoryBean
对象,进而实现对多个不同的数据源的操纵。
注意❗:SpringBoot
实际上连接多数据源的方式有很多种,也有很多成熟的技术选型,本文所提供的思路仅是为了帮助读者加深SqlSessionFactoryBean
的理解和使用。
什么是多数据源
在现代软件架构中,多数据源
指的是应用程序配置和连接到多个数据库实例的能力。这种架构允许应用程序根据不同的业务需求、数据类型或性能要求,与多个独立的数据库环境交互。在实现上,每个数据源都有自己的连接池、事务管理和数据访问对象。
上述专业定义可能有些晦涩难懂,其实你完全可以将多数据源
的概念可以类比于一个大型学校里有多个图书馆和图书管理员的情况。每个图书馆(数据源)由不同的图书管理员(数据库管理系统)负责,管理着特定类型的书籍(数据)。
比如,一个图书馆可能专注于科学书籍,而另一个专门存放文学作品。这样的安排不仅提高了查找信息的效率——因为每个管理员都对自己的领域非常了解,同时还增强了安全性——因为可以为不同类型的数据设置不同级别的保护。
随着学校(业务)的发展,可能需要新的图书馆来容纳更多的书籍(数据),这时多图书馆的布局就显得尤为重要。总而言之,多数据源
在软件应用中的作用就像这些图书馆和图书管理员一样,确保数据的有效管理、安全和高效访问。"
如上这张图就反映了应用中多数据源和单数据源之间的区别。接下来,我们就来分析在SpringBoot
应用中,如何通过配置SqlSessionFactoryBean
来实现多数据源的连接。
环境搭建
工欲善其事必先利其器,开始动手之前我们先来对构建案例所需的环境进行一个简单的介绍。后续案例所需的关键依赖如下:
SpringBoot
的构建web
应用的关键依赖:Spring-boot-starter-web
SpringBoot
整合Mybatis
的关键Starter:mybatis-spring-boot-starter
mysql
的jdbc
连接依赖:mysql-connector-java
- 数据连接池
druid
:druid-spring-boot-starter
项目整体结构如下:
dao1
:数据源1
所对应的数据Mapper
接口;dao2
:数据源2
所对应的数据Mapper
接口;config
: 通过@Configuration
标注的配置类信息。
除此之外,我们还需要准备两个数据源信息,在此笔者准了如下所示的test_db
和test_db1
两个数据库,其内部均有一张t_user
的数据表。
t_user
数据表包含name
和type
两个字段信息。
实战双数据源配置
在开始之前,我们先来简单回顾下SpringBoot
集成Mybatis
时在连接单数据源时是如何进行配置的:
spring:
datasource:
username: root
password: root
# allowMultiQueries表示支持执行;间隔的多个sql nullCatalogMeansCurrent=true返回指定库涉及的表
jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
# 使用的连接池的类型
type: com.alibaba.druid.pool.DruidDataSource
在上述配置文件中,我们主要配置了如下内容:
- 数据库URL (
spring.datasource.url
): 这是数据库服务器的地址和数据库名。它通常包含协议(例如jdbc:mysql:
)、主机地址、端口号(对于MySQL,默认是3306),以及要连接的数据库名。例如:jdbc:mysql://localhost:3306/test_db
- 用户名 (
spring.datasource.username
): 用于连接数据库的用户名。 - 密码 (
spring.datasource.password
): 用于连接数据库的密码。 - 驱动类名 (
spring.datasource.driver-class-name
): 这是JDBC
驱动的完整类名,它用于告诉Spring Boot
应用程序使用哪种数据库。例如,对于MySQL
,通常是com.mysql.cj.jdbc.Driver
。
当我们配置多数据源时,配置文件需要做如下的修改:
spring:
# 数据源1
primary:
username: root
password: root
jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
# 使用的连接池的类型
type: com.alibaba.druid.pool.DruidDataSource
# 数据源2
slave:
username: root
password: root
jdbc-url: jdbc:mysql://127.0.0.1:3306/test_db1?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&tcpKeepAlive=true&autoReconnect=true&allowMultiQueries=true&nullCatalogMeansCurrent=true
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
此时,我们将之前配置文件中datasource
改为了primary
和 slave
,这样SpringBoot
就不再会为我们设定默认数据库。与此同时,我们将url
改为了jdbc-url
。这是因为
当只有单个数据源时,SpringBoot
会默认将url
映射为 jdbc-url
进行映射,进而保证我们获得数据源的成功注入。
此外,由于我们不再使用SpringBoot
的默认配置来加载数据源,所以需要手动设置的数据源的连接地址,如果不进行修改,则会导致项目无法启动,进而出现 jdbcUrl is required with driverClassName
的异常。
处理好配置文件后,我们需要构建出DataSource
、SqlSessionFactory
从而实现对SqlSessionFactoryBean
的定制化配置,其具体配置如下:
@Configuration
@MapperScan(basePackages = "com.example.dao1", sqlSessionFactoryRef = "sqlSessionFactory1")
public class DataSource1Config {
@Bean
@ConfigurationProperties(prefix = "spring.primary")
public DataSource dataSourcePrimary() {
return DataSourceBuilder.create().build();
}
@Bean
public SqlSessionFactory sqlSessionFactory1() throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSourcePrimary());
String locationPattern = "classpath*:/mapperPrimary/*.xml";
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
return sessionFactoryBean.getObject();
}
@Bean(name = "sqlSessionTemplate1")
public SqlSessionTemplate sqlSessionTemplate1(@Qualifier("sqlSessionFactory1") SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
当我们期待使用Mybatis
操作多数据源时,对于不同的数据源,我们都需要定义不同的Mapper
接口和XML
映射文件,以确保最终生成的Mapper
实现类可以操纵不同的数据源信息。所以,其中的dataSourcePrimary
就是为了加载dataSourcePrimary
指定的数据源信息,确保构建的数据源最终连接到Primary
中指定的数据库信息。而在sqlSessionFactory
的构建中,则主要通过SqlSessionFactoryBean
来构建出一个SqlSessionFactory
并注入容器,而在这一过程中需要设定Mapper
接口所对应的配置文件。
slave
的配置可参考DataSource1Config
进行配置,在此便不进行赘述。接下来,我们来看下最终的效果:
@RestController
@RequestMapping("/data")
@Slf4j
public class DataSourceController {
@Autowired
private User1Mapper userMapper;
@Autowired
private User2Mapper user2Mapper;
@GetMapping("/get-user1/{name}")
public User getUserFromTestDb(@PathVariable("name") String userName) {
return userMapper.selectUser(userName);
}
@GetMapping("/get-user2/{name}")
public User getUserFromTestDb2(@PathVariable("name") String userName) {
return user2Mapper.selectUser(userName);
}
}
getUserFromTestDb
用于从数据源test_db
获取数据getUserFromTestDb2
用于从数据源test_db1
获取数据
最终效果如下:
访问数据源1
访问数据源2
总结
接下来,我们对上述程序用到的组件进行一个简要的总结和回顾
-
数据源(
DataSource
)。数据源是数据库连接的工厂。在Spring
中,DataSource
对象负责提供数据库连接。当配置多个数据源时,每个数据源都对应不同的数据库连接信息。例如,一个数据源可能连接到数据库test_db
,而另一个连接到数据库test_db1
。 -
Mybatis的SqlSessionFactory
。SqlSessionFactory
是Mybatis
中的一个核心组件,它负责创建SqlSession
。SqlSession
提供了执行SQL
命令、获取映射器和管理事务的方法。在配置多个数据源的情况下,每个数据源都需要有对应的SqlSessionFactory
,以确保SQL
操作能够针对正确的数据库执行。 -
@MapperScan
注解的使用。该注解用于指定哪些包中的接口应该被Mybatis
识别为映射器(Mapper
)。在多数据源配置中,可以使用不同的@MapperScan
注解来指定不同数据源的映射器。
更进一步,SpringBoot
集成Mybatis
实现多数据源的基本流程如下:
- 为每个数据源定义独立的配置,包括
DataSource、SqlSessionFactory
。 - 使用
@MapperScan
为每个数据源指定Mapper
接口的位置。 - 将配置好的
SqlSessionFactory
交由SpringBoot
容器进行管理
这样,当应用程序运行时,只需要注入不同数据源对应的Mapper
即可访问不同的数据库,而无需担心数据源之间的冲突和干扰。
最后,希望本文对你对有助于加深理解SpringBoot
集成Mybatis
的原理。
笔者
在此建议,笔者
专栏的文章是成体系的,从头开始读效果更佳哦!当然觉得文章还可以的话,不妨点赞+收藏+关注,不错过之后的每一次更新。
转载自:https://juejin.cn/post/7302344328244363274