5.多数据源配置与使用
虽然我们前面的db系列教程更多的是基于单数据源的db操作,但是实际的业务开发中,难免会遇到一个项目配置多个数据源的情况,接下来本文将介绍一下多个数据源可以怎么配置,我们的JdbcTemplate又应该如何获取
I. 环境准备
1. 数据库相关
以mysql为例进行演示说明,因为需要多数据源,一个最简单的case就是一个物理库上多个逻辑库,本文是基于本机的mysql进行操作
创建数据库test
与 story
,两个库下都存在一个表money
(同名同结构表,但是数据不同哦)
CREATE TABLE `money` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '' COMMENT '用户名',
`money` int(26) NOT NULL DEFAULT '0' COMMENT '钱',
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `name` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
2. 项目环境
本项目借助SpringBoot 2.2.1.RELEASE
+ maven 3.5.3
+ IDEA
进行开发
下面是核心的pom.xml
(源码可以再文末获取)
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
配置文件信息application.yml
# 数据库相关配置
spring:
datasource:
story:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
test:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
# 日志相关
logging:
level:
root: info
org:
springframework:
jdbc:
core: debug
请注意上面的数据库配置,我们前面介绍的但数据库配置如下,它们层级并不一样,上面的配置需要我们自己额外进行加载解析
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password:
II. 多数据源支持
1. 数据源配置
SpringBoot帮我们省略了很多操作,单数据源时,在yaml文件中配置数据库相关信息之后,我们不需要任何其他操作,Spring会帮我们实例对应的DataSource
,然后借助它来创建JdbcTemplate
而多数据源则需要我们自己来额外处理了,请注意上面的配置信息,和默认的配置没什么差别,只是前缀多了一层,我们可以借助@ConfigurationProperties
来加载配置文件
@Configuration
public class DataSourceConfiguration {
@Primary
@Bean(name = "storyDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.story")
public DataSourceProperties storyDataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "storyDataSource")
public DataSource storyDataSource(@Qualifier("storyDataSourceProperties") DataSourceProperties storyDataSourceProperties) {
return storyDataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean(name = "testDataSourceProperties")
@ConfigurationProperties(prefix = "spring.datasource.test")
public DataSourceProperties testDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "testDataSource")
public DataSource testDataSource(@Qualifier("testDataSourceProperties") DataSourceProperties testDataSourceProperties) {
return testDataSourceProperties.initializeDataSourceBuilder().build();
}
}
配置代码如上,一个是将数据源配置映射为bean DataSourceProperties
, 一个是根据数据源配置实例化DataSource
;
此外两个@Primary
注解,主要是为了设置默认的数据源
2. JdbcTemplate实例化
数据源已经获取到之后,再实例化JdbcTemplate
就很简单了,除了直接声明bean之外,也可以基于DataSource
来手动创建临时对象,下面给出两种使用姿势
定义对应的bean
,对于业务使用更友好
@Bean("storyJdbcTemplate")
public JdbcTemplate storyJdbcTemplate(@Qualifier("storyDataSource") DataSource storyDataSource) {
return new JdbcTemplate(storyDataSource);
}
@Bean("testJdbcTemplate")
public JdbcTemplate testJdbcTemplate(@Qualifier("testDataSource") DataSource testDataSource) {
return new JdbcTemplate(testDataSource);
}
借助ApplicationContext
来实例化JdbcTemplate,使用更灵活
@Service
public class JdbcServer implements ApplicationContextAware {
private JdbcTemplate storyJdbcTemplate;
private JdbcTemplate testJdbcTemplate;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
Map<String, DataSource> map = applicationContext.getBeansOfType(DataSource.class);
System.out.println(map);
storyJdbcTemplate = new JdbcTemplate(map.get("storyDataSource"));
testJdbcTemplate = new JdbcTemplate(map.get("testDataSource"));
}
}
3. 测试case
最后简单测试一下上面创建的两个JdbcTemplate
是否访问不同的数据库
public void query() {
List<Map<String, Object>> storyRes = storyJdbcTemplate.queryForList("select * from money where id in (1, 1000)");
List<Map<String, Object>> testRes = testJdbcTemplate.queryForList("select * from money where id in (1, 1000)");
System.out.println(storyRes);
System.out.println("--------------");
System.out.println(testRes);
}
启动类如下
@SpringBootApplication
public class Application {
public Application(JdbcServer jdbcServer) {
jdbcServer.query();
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
相同的sql,获取的结果并不一样,分别从两个库中获取的数据
4. 小结
使用多数据源,比较简单的思路就是自定义配置的加载方式,获取不同的DataSourceProperties
对象,然后基于它来创建DataSource
实例
利用JdbcTemplate
来操作db的应用场景,直接选择不同的数据源Datasource
就行了
当然实际的项目中,我们一般会借助Herbernate
、Myabtis
、Jooq
等orm框架,那么使用orm时,多数据源又应该怎么处理呢? (请持续关注,相关博文即将上线)
II. 其他
0. 项目
系列博文
- 【DB系列】JdbcTemplate之数据插入使用姿势详解
- 【DB系列】JdbcTemplate之数据查询上篇
- 【DB系列】JdbcTemplate之数据查询下篇
- 【DB系列】JdbcTemplate之数据更新与删除
- 【DB系列】声明式事务Transactional
- 【DB系列】事务隔离级别知识点小结
- 【DB系列】事务传递属性
- 【DB系列】事务不生效的几种case
- 【DB系列】编程式事务使用姿势介绍篇
项目源码