Spring Boot 配置多資料來源
作者:Grey
原文地址:
說明
本文主要介紹了 Spring Boot 下如何配置多資料來源。
環境和版本
Java 版本:17
Spring Boot 版本:3.0.0
資料庫:H2
注:本示例基於 JdbcTemplate,如果使用 JPA,Hiberante 或者 Mybatis 等,方法類似。
程式碼說明
首先,配置兩個資料來源,這裡我們基於 H2 配置了兩個簡單資料來源,由於 H2 是記憶體資料庫,無需手動新建
foo.datasource.url=jdbc:h2:mem:foo
foo.datasource.username=sa
foo.datasource.password=
foo.datasource.driver-class-name=org.h2.Driver
bar.datasource.url=jdbc:h2:mem:bar
bar.datasource.username=sa
bar.datasource.password=
bar.datasource.driver-class-name=org.h2.Driver
接下來在 resources 新建一個 db 資料夾,裡面存兩個資料庫的初始化指令碼
schema.sql
DROP TABLE IF EXISTS USER_INFO;
CREATE TABLE USER_INFO
(
id INT AUTO_INCREMENT PRIMARY KEY,
user_name VARCHAR(250) NOT NULL,
email VARCHAR(250) DEFAULT NULL
);
foo 資料來源的初始化資料 foo-data.sql
INSERT INTO
USER_INFO (user_name, email)
VALUES
('grey-foo', 'abc@gmail.com'),
('jack-foo', 'jack@email.com');
bar 資料來源的初始化資料 bar-data.sql
INSERT INTO USER_INFO (user_name, email)
VALUES ('grey-bar', 'abc@gmail.com'),
('jack-bar', 'jack@email.com');
指令碼和資料來源配置好以後,接下來要準備兩個資料來源的配置類資訊,以任意一個資料來源的配置類資訊為例(另外一個同理)
foo 資料來源的配置資訊如下
@Configuration
@ConfigurationProperties(prefix = "foo.datasource")
@Slf4j
public class FooDataSourceConfig {
@Bean
public PlatformTransactionManager fooTxManager(DataSource fooDataSource) {
return new DataSourceTransactionManager(fooDataSource);
}
@Bean
public DataSourceProperties fooDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
public DataSource fooDataSource() {
DataSourceProperties dataSourceProperties = fooDataSourceProperties();
// schema init
DatabasePopulator databasePopulator =
new ResourceDatabasePopulator(
new ClassPathResource("db/schema.sql"), new ClassPathResource("db/foo-data.sql"));
DataSource ds = dataSourceProperties.initializeDataSourceBuilder().build();
DatabasePopulatorUtils.execute(databasePopulator, ds);
log.info("foo datasource: {}", dataSourceProperties.getUrl());
return ds;
}
@Bean
@Primary
public JdbcTemplate fooJdbcTemplate(@Qualifier("fooDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
需要注意的點,@Primary
引數定義了該資料來源是主資料來源,也就是說,呼叫資料來源的時候,如果沒有指定名稱預設就是用這個資料來源。
在fooDataSource
中,定義了初始化指令碼的位置
DatabasePopulator databasePopulator =
new ResourceDatabasePopulator(
new ClassPathResource("db/schema.sql"), new ClassPathResource("db/foo-data.sql"));
另外一個 BarDataSourceConfig
同理。
完成上述配置後,在啟動類中注入這兩個資料來源對應的JdbcTemplate
@SpringBootApplication
@Slf4j
public class SpringMultiDatasourceApplication implements CommandLineRunner {
private final JdbcTemplate fooTemplate;
private final JdbcTemplate barTemplate;
private final JdbcTemplate defaultTemplate;
public SpringMultiDatasourceApplication(
@Qualifier("fooJdbcTemplate") JdbcTemplate fooTemplate,
@Qualifier("barJdbcTemplate") JdbcTemplate barTemplate,
JdbcTemplate defaultTemplate) {
this.fooTemplate = fooTemplate;
this.barTemplate = barTemplate;
this.defaultTemplate = defaultTemplate;
}
@Override
public void run(String... args) throws Exception {
fooTemplate.queryForList("SELECT * FROM USER_INFO").forEach(row -> log.info(row.toString()));
log.info("----");
barTemplate.queryForList("SELECT * FROM USER_INFO").forEach(row -> log.info(row.toString()));
log.info("----");
defaultTemplate
.queryForList("SELECT * FROM USER_INFO")
.forEach(row -> log.info(row.toString()));
}
public static void main(String[] args) {
SpringApplication.run(SpringMultiDatasourceApplication.class, args);
}
}
本示例中,注入了三個JdbcTemplate
,其中兩個透過@Qualifier
指定了名稱,還有一個defaultTemplate
並未指定名稱,所以取的就是有@Primary
註解的JdbcTemplate
。
執行主函式,列印出如下資訊
{ID=1, USER_NAME=grey-foo, EMAIL=abc@gmail.com}
{ID=2, USER_NAME=jack-foo, EMAIL=jack@email.com}
----
{ID=1, USER_NAME=grey-bar, EMAIL=abc@gmail.com}
{ID=2, USER_NAME=jack-bar, EMAIL=jack@email.com}
----
{ID=1, USER_NAME=grey-foo, EMAIL=abc@gmail.com}
{ID=2, USER_NAME=jack-foo, EMAIL=jack@email.com}
可以看到效果,預設的JdbcTemplate
取的是 foo 資料來源的資訊。