思考,输出,沉淀。用通俗的语言陈述技术,让自己和他人都有所收获。
作者:毅航😜
在从BeanFactory入手,讲透Spring整合Mybatis的底层原理一文中,我们对Spring整合Mybatis的底层原理进行的剖析,总的来看其本质就是将MyBatis所需要的bean通过Spring的FactoryBean注入到容器,进而以交由容器管理,而实现这一逻辑的关键对象为——SqlSessionFactoryBean。
本文主要分析讨论在SpringBoot应用中我们该如何配置SqlSessionFactoryBean对象,进而实现对多个不同的数据源的操纵。
注意❗:SpringBoot实际上连接多数据源的方式有很多种,也有很多成熟的技术选型,本文所提供的思路仅是为了帮助读者加深SqlSessionFactoryBean的理解和使用。
什么是多数据源
在现代软件架构中,多数据源指的是应用程序配置和连接到多个数据库实例的能力。这种架构允许应用程序根据不同的业务需求、数据类型或性能要求,与多个独立的数据库环境交互。在实现上,每个数据源都有自己的连接池、事务管理和数据访问对象。
上述专业定义可能有些晦涩难懂,其实你完全可以将多数据源的概念可以类比于一个大型学校里有多个图书馆和图书管理员的情况。每个图书馆(数据源)由不同的图书管理员(数据库管理系统)负责,管理着特定类型的书籍(数据)。
比如,一个图书馆可能专注于科学书籍,而另一个专门存放文学作品。这样的安排不仅提高了查找信息的效率——因为每个管理员都对自己的领域非常了解,同时还增强了安全性——因为可以为不同类型的数据设置不同级别的保护。
随着学校(业务)的发展,可能需要新的图书馆来容纳更多的书籍(数据),这时多图书馆的布局就显得尤为重要。总而言之,多数据源在软件应用中的作用就像这些图书馆和图书管理员一样,确保数据的有效管理、安全和高效访问。"
如上这张图就反映了应用中多数据源和单数据源之间的区别。接下来,我们就来分析在SpringBoot应用中,如何通过配置SqlSessionFactoryBean来实现多数据源的连接。
环境搭建
工欲善其事必先利其器,开始动手之前我们先来对构建案例所需的环境进行一个简单的介绍。后续案例所需的关键依赖如下:
SpringBoot的构建web应用的关键依赖:Spring-boot-starter-webSpringBoot整合Mybatis的关键Starter:mybatis-spring-boot-startermysql的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的原理。
笔者在此建议,笔者专栏的文章是成体系的,从头开始读效果更佳哦!当然觉得文章还可以的话,不妨点赞+收藏+关注,不错过之后的每一次更新。