来一块玩SpringBoot(肆) StringBoot添加多数据源

SpringBoot多数据源

实现目标

  1. 添加两个数据源
  2. 分别在两个数据源中创建表并插入数据
  3. 分别查询并输出两个数据源中表的数据

    环境:

  4. SpringBoot 2.1.7RELEASE

  5. JDK1.8
  6. spring-boot-starter-jdbc
  7. spring-boot-starter-web
  8. h2(runtime)
  9. spring-boot-starter-actuator

    Action:

    流程:
  10. 搭建项目

  11. 配置数据源
  12. 创建数据源
  13. 分别向数据源中创建表并且插入数据
  14. 分别查询并输出数据源中的数据

省略搭建项目的流程,搭建项目请参考《来一块玩SpringBoot(壹) 创建SpringBoot项目》

配置数据源

为了便于管理,配置信息一般同SptingBoot的配置信息存放在一起(本Demo存放在classpath/application.properties 中)。

当你配置多数据源的时候,即使两个数据源仅有url不一样,也要分开写,这样方便于后期的维护。

actuator配置和数据源配置:

1
2
3
4
5
6
7
8
9
10
management.endpoints.web.exposure.include=*


head.datasource.url=jdbc:h2:mem:headdb
head.datasource.username=SA
heda.datasource.password=

foot.datasource.url=jdbc:h2:mem:footdb
foot.datasource.username=SA
foot.datasource.password=
创建数据源

创建多个数据源就不能在使用SpringBoot的自动配置了,我们在*Application.java中将相关的自动配置排除。

image.png

DataSourceAutoConfiguration.class 是数据源的自动配置

DataSourceTransactionManagerAutoConfiguration.class 是数据源事务的自动配置

JdbcTemplateAutoConfiguration.class 是JdbcTemplate的自动配置

创建HeadDatasource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Bean
@ConfigurationProperties("head.datasource")
public DataSourceProperties headDataSourceProperties(){
return new DataSourceProperties();
}
@Bean
@Primary
public DataSource headDatasource() {
DataSourceProperties dataSourceProperties = headDataSourceProperties();
log.info("head datasource: {}", dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean
public PlatformTransactionManager headTransactionManager(DataSource headDatasource){
return new DataSourceTransactionManager(headDatasource);
}
@Bean
public JdbcTemplate headJdbcTemplate( DataSource headDatasource) {
return new JdbcTemplate(headDatasource);
}

headDataSourceProperties() 读取head.datasource.*配置

headDatasource() 构建数据源

headTransactionManager() 创建事务

headJdbcTemplate() 创建该数据源的JdbcTemplate,后面操作head_glitter数据库就用该JdbcTemplate

创建HeadDatasource:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Bean
@ConfigurationProperties("foot.datasource")
public DataSourceProperties footDataSourceProperties(){
return new DataSourceProperties();
}
@Bean
public PlatformTransactionManager footTransactionManager(DataSource footDatasource){
return new DataSourceTransactionManager(footDatasource);
}

@Bean
public DataSource footDataSource() {
DataSourceProperties dataSourceProperties = footDataSourceProperties();
log.info("foot datasource: {}", dataSourceProperties.getUrl());
return dataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean(name = "footJdbcTemplate")
public JdbcTemplate footJdbcTemplate( DataSource footDatasource) {
return new JdbcTemplate(footDatasource);
}

footDataSourceProperties() 读取foot.datasource.*配置

footTransactionManager() 构建数据源

footDataSource() 创建事务

footJdbcTemplate() 创建该数据源的JdbcTemplate,后面操作foot_glitter数据库就用该JdbcTemplate

向数据源创建表并插入数据

创建一类并实现CommandLineRunner接口(注意,该类需注册成Bean),并重写run方法

image.png
image.png

向该类注入headJdbcTemplatefootJdbcTemplate,用以向数据源初始化表和插入数据:

1
2
3
4
5
6
7
8
9
10
11
12
@Autowired
private JdbcTemplate headJdbcTemplate;

@Autowired
private JdbcTemplate footJdbcTemplate;

private void initSchema(){
headJdbcTemplate.execute("CREATE TABLE HEAD_GLITTER(ID INT IDENTITY, NAME VARCHAR(64));");
headJdbcTemplate.execute("INSERT INTO HEAD_GLITTER(ID,NAME) VALUES (1,'PLAYER');INSERT INTO HEAD_GLITTER(ID,NAME) VALUES (2,'FULINLIN')");
footJdbcTemplate.execute("CREATE TABLE FOOT_GLITTER(ID INT IDENTITY, NAME VARCHAR(64));");
footJdbcTemplate.execute("INSERT INTO FOOT_GLITTER(ID,NAME) VALUES (1,'PLAYER');INSERT INTO FOOT_GLITTER(ID,NAME) VALUES (2,'FULINLIN');");
}

在该类中添加查询数据的方法:

1
2
3
4
5
6
7
8
9
10
private void showHeadData(){
headJdbcTemplate.queryForList("SELECT * FROM HEAD_GLITTER")
.forEach(row->log.info("HeadData:{}",row.toString()));
}


private void showFootData(){
footJdbcTemplate.queryForList("SELECT * FROM FOOT_GLITTER")
.forEach(row->log.info("FootData:{}",row.toString()));
}

在run方法中执行 initSchema()showHeadData()showFootData() ,一定先执行initSchema()

该类的最终代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
package com.glitter.player.springbootmultipledatasource;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

/**
* @program:
* @author: Player
* @create: 2019-08-15
**/
@Component
@Slf4j
public class JDBCRunner implements CommandLineRunner {

@Autowired
private JdbcTemplate headJdbcTemplate;

@Autowired
private JdbcTemplate footJdbcTemplate;

private void showHeadData(){
headJdbcTemplate.queryForList("SELECT * FROM HEAD_GLITTER")
.forEach(row->log.info("HeadData:{}",row.toString()));
}


private void showFootData(){
footJdbcTemplate.queryForList("SELECT * FROM FOOT_GLITTER")
.forEach(row->log.info("FootData:{}",row.toString()));
}

private void initSchema(){
headJdbcTemplate.execute("CREATE TABLE HEAD_GLITTER(ID INT IDENTITY, NAME VARCHAR(64));");
headJdbcTemplate.execute("INSERT INTO HEAD_GLITTER(ID,NAME) VALUES (1,'PLAYER');INSERT INTO HEAD_GLITTER(ID,NAME) VALUES (2,'FULINLIN')");
footJdbcTemplate.execute("CREATE TABLE FOOT_GLITTER(ID INT IDENTITY, NAME VARCHAR(64));");
footJdbcTemplate.execute("INSERT INTO FOOT_GLITTER(ID,NAME) VALUES (1,'PLAYER');INSERT INTO FOOT_GLITTER(ID,NAME) VALUES (2,'FULINLIN');");
}


@Override
public void run(String... args) {
initSchema();
showHeadData();
showFootData();
}
}
验证结果

启动项目之后可以看到控制台日志正常输出我们想要的结果: 两个库所有的数据

image.png

打开浏览器访问http://localhost:8080/actuator/beans(该链接可以查看当前项目中所有的bean信息)

可以看到该项目中有我们创建的两个Datasource的bean( headDatasourcefootDatasource

同时也可以看到两个JdbcTemplate的bean( headJdbcTemplatefootJdbcTemplate )

image.png
image.png
项目结构
image.png
image.png