avatar

Spring Boot 配置多数据源demo

SpringBoot 配置多数据源的笔记总结.

首先,通过 spring initializr 新建一个Spring Boot项目. 为了方便,选择H2作为我们的数据库,选择web, h2, lombok等几个依赖,生成我们的Spring Boot项目.

默认情况下,Spring Boot 会帮我们自动装配

  1. DataSourceAutoConfiguration.class,
  2. JdbcTemplateAutoConfiguration.class,
  3. DataSourceTransactionManagerAutoConfiguration.class

这三个类数据源相关的类,为了配置多个数据源,我们需要手动排除掉Spring Boot为我们自动配置的类,同时我们自己手动配置了两个数据源,分别命名为 foobar, 相关代码如下:

java
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
50
51
52
53
54
55
56
57
58
59
60
61
62
@Slf4j
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class,
JdbcTemplateAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class})
// 排除掉Spring boot自动装配的类
public class DatasourceDemoApplication {

public static void main(String[] args) {
SpringApplication.run(DatasourceDemoApplication.class, args);
}



@Bean
@ConfigurationProperties("bar.datasource")
public DataSourceProperties barDatasourceProp() {
return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("foo.datasource")
public DataSourceProperties fooDatasourceProp() {
return new DataSourceProperties();
}


@Bean
public DataSource barDatasource() {
DataSourceProperties dsProp = barDatasourceProp();
log.info("bar ds url:{}", dsProp.getUrl());
return dsProp.initializeDataSourceBuilder().build();
}

@Bean
public DataSource fooDatasource() {
DataSourceProperties dsProp = fooDatasourceProp();
log.info("foo ds url:{}", dsProp.getUrl());
return dsProp.initializeDataSourceBuilder().build();
}

@Bean
public JdbcTemplate fooJdbcTemplate() {
DataSource foo = fooDatasource();
return new JdbcTemplate(foo);
}

@Bean
public JdbcTemplate barJdbcTemplate() {
DataSource bar = barDatasource();
return new JdbcTemplate(bar);
}

@Bean
public DataSourceTransactionManager barTxManager() {
return new DataSourceTransactionManager(barDatasource());
}

@Bean
public DataSourceTransactionManager fooTxManager() {
return new DataSourceTransactionManager(fooDatasource());
}
}

相应的配置文件application.properties配置项:

properties
1
2
3
4
5
6
7
foo.datasource.url=jdbc:h2:mem:foo
foo.datasource.username=sa
foo.datasource.password=

bar.datasource.url=jdbc:h2:mem:bar
bar.datasource.username=sa
bar.datasource.password=

之后我们可以写个测试类测试一下,我这里用的是一个Controller类,代码如下:

java
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.*;

@RestController
@RequestMapping("ds")
@Slf4j
public class DataSourceDemoController {

@Resource(name="fooDatasource")
DataSource fooDS;

@Resource(name="barDatasource")
DataSource barDS;

@Resource(name="fooJdbcTemplate")
JdbcTemplate fooJdbc;

@Resource(name="barJdbcTemplate")
JdbcTemplate barJdbc;

@PostMapping("fooInsert")
public String insertDataWithFoo() {
try {
String sql = "INSERT INTO USER (name) VALUES ('foo')";
fooJdbc.execute(sql);
} catch (Exception e) {
log.error("error:{}", e.getMessage());
}

return "success";
}

@PostMapping("createTable")
public String createTable() {
Connection conn = null;
try {
conn = fooDS.getConnection();
log.info("conn:{}", conn);
Statement stmt = conn.createStatement();
stmt.execute("DROP TABLE IF EXISTS `USER`");
stmt.execute("CREATE TABLE `USER` (id INTEGER PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100));");

} catch (SQLException e) {
log.error("errors occur when creating table:{} ", e.getMessage());
} finally {
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.error("exception occurs: ", e);
}
}
}
return "success";
}


@GetMapping("barSelect")
public String selectDataWithBar() {

try {
barJdbc.queryForList("SELECT * FROM `USER`").forEach(row -> System.out.println(row));
} catch (Exception e) {
return e.getMessage();
}
return "success";
}

@GetMapping("fooSelect")
public String selectDataWithFoo() {
try {
fooJdbc.queryForList("SELECT * FROM `USER`").forEach(row -> System.out.println(row));
} catch (Exception e) {
return e.getMessage();
}
return "success";
}


}

通过访问 /ds/createTable 先在 foo 数据源新建一个USER 表, 再通过 /ds/fooInsert 插入一条数据。通过访问 /ds/barSelect 会发现返回 “==Table USER NOT EXIST==“ 这样的报错,说明我们刚刚的 USER表确实是来自于 foo 数据源而不是 bar 数据源。 最后通过 /ds/fooSelect 查询一下刚刚插入进去的记录,发现确实是插入成功的。由此证明了我们刚刚确实是配置了两个数据源,而且通过这两个数据源确实也访问到了来源不同的数据。


以上

文章作者: JanGin
文章链接: http://jangin.github.io/2020/07/31/springboot-mulit-datasource-demo/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 JanGin's BLOG

评论