1. Overview
1.概述
The typical scenario for a Spring Boot application is to store data in a single relational database. But we sometimes need to access multiple databases.
Spring Boot应用程序的典型场景是将数据存储在一个关系型数据库中。但我们有时需要访问多个数据库。
In this tutorial, we’ll learn how to configure and use multiple data sources with Spring Boot.
在本教程中,我们将学习如何用Spring Boot配置和使用多个数据源。
To find out how to deal with a single data source, check out our introduction to Spring Data JPA.
要了解如何处理单个数据源,请查看我们的Spring Data JPA介绍。
2. Default Behavior
2.默认行为
Let’s remember what declaring a data source in Spring Boot looks like in application.yml:
让我们记住在Spring Boot中声明数据源在application.yml中的样子。
spring:
datasource:
url: ...
username: ...
password: ...
driverClassname: ...
Internally, Spring maps these settings to an instance of org.springframework.boot.autoconfigure.jdbc.DataSourceProperties.
在内部,Spring将这些设置映射到org.springframework.boot.autoconfigure.jdbc.DataSourceProperties的一个实例。
Let’s take a look into the implementation:
让我们看一下实施情况。
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
// ...
/**
* Fully qualified name of the JDBC driver. Auto-detected based on the URL by default.
*/
private String driverClassName;
/**
* JDBC URL of the database.
*/
private String url;
/**
* Login username of the database.
*/
private String username;
/**
* Login password of the database.
*/
private String password;
// ...
}
We should point out the @ConfigurationProperties annotation that maps the properties of the configuration to the Java object automatically.
我们应该指出@ConfigurationProperties注解,它将配置的属性自动映射到Java对象上。
3. Extending the Defaults
3.扩展默认值
So, to use multiple data sources, we need to declare multiple beans with different mappings within Spring’s application context.
因此,为了使用多个数据源,我们需要在Spring的应用上下文中声明具有不同映射的多个Bean。
We can do this by using a configuration class:
我们可以通过使用一个配置类来做到这一点。
@Configuration
public class TodoDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.todos")
public DataSourceProperties todosDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("spring.datasource.topics")
public DataSourceProperties topicsDataSourceProperties() {
return new DataSourceProperties();
}
}
The configuration for the data sources must look like this:
数据源的配置必须看起来像这样。
spring:
datasource:
todos:
url: ...
username: ...
password: ...
driverClassName: ...
topics:
url: ...
username: ...
password: ...
driverClassName: ...
Then we can create the data sources by using the DataSourceProperties objects:
然后我们可以通过使用DataSourceProperties对象来创建数据源。
@Bean
public DataSource todosDataSource() {
return todosDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
@Bean
public DataSource topicsDataSource() {
return topicsDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
4. Spring Data JDBC
4.Spring Data JDBC
When using Spring Data JDBC, we also need to configure one instance of JdbcTemplate for each DataSource:
当使用Spring Data JDBC时,我们还需要为每个DataSource配置一个JdbcTemplate的实例。
@Bean
public JdbcTemplate todosJdbcTemplate(@Qualifier("todosDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
@Bean
public JdbcTemplate topicsJdbcTemplate(@Qualifier("topicsDataSource") DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
We can then use them also by specifying a @Qualifier:
然后我们也可以通过指定一个@Qualifier来使用它们。
@Autowired
@Qualifier("topicsJdbcTemplate")
JdbcTemplate jdbcTemplate;
5. Spring Data JPA
5.Spring Data JPA
When using Spring Data JPA, we want to use repositories like the following, where Todo is the entity:
当使用Spring Data JPA时,我们希望使用如下的存储库,其中Todo是实体。
public interface TodoRepository extends JpaRepository<Todo, Long> {}
So, we need to declare EntityManager factories for each data source:
因此,我们需要为每个数据源声明EntityManager工厂。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackageClasses = Todo.class,
entityManagerFactoryRef = "todosEntityManagerFactory",
transactionManagerRef = "todosTransactionManager"
)
public class TodoJpaConfiguration {
@Bean
public LocalContainerEntityManagerFactoryBean todosEntityManagerFactory(
Qualifier("todosDataSource") DataSource dataSource,
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(todosDataSource())
.packages(Todo.class)
.build();
}
@Bean
public PlatformTransactionManager todosTransactionManager(
@Qualifier("todosEntityManagerFactory") LocalContainerEntityManagerFactoryBean todosEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(todosEntityManagerFactory.getObject()));
}
}
Let’s look at a few restrictions that we should be aware of.
让我们来看看我们应该注意的几个限制。
We need to split the packages to allow one @EnableJpaRepositories for each data source.
我们需要分割软件包,以便为每个数据源提供一个@EnableJpaRepositories。
Unfortunately, to get EntityManagerFactoryBuilder injected, we need to declare one of the data sources as @Primary.
不幸的是,为了让EntityManagerFactoryBuilder被注入,我们需要将其中一个数据源声明为@Primary。
This is because EntityManagerFactoryBuilder is declared in org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration, and this class needs a single data source injected. Usually, some parts of the framework might not expect multiple data sources configured.
这是因为EntityManagerFactoryBuilder是在org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration中声明的,而这个类需要注入一个数据源。通常情况下,框架的某些部分可能不希望配置多个数据源。
6. Configure Hikari Connection Pool
6.配置Hikari连接池
If we want to configure Hikari, we just need to add an @ConfigurationProperties to the data source definition:
如果我们想配置Hikari,我们只需要在数据源定义中添加一个@ConfigurationProperties。
@Bean
@ConfigurationProperties("spring.datasource.todos.hikari")
public DataSource todosDataSource() {
return todosDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
Then we can insert the following lines into the application.properties file:
然后我们可以在application.properties文件中插入以下几行。
spring.datasource.todos.hikari.connectionTimeout=30000
spring.datasource.todos.hikari.idleTimeout=600000
spring.datasource.todos.hikari.maxLifetime=1800000
7. Conclusion
7.结语
In this article, we learned how to configure multiple data sources with Spring Boot.
在这篇文章中,我们学习了如何用Spring Boot配置多个数据源。
We saw that we need some configuration and that there might be pitfalls when deviating from the standard but that it is possible in the end.
我们看到,我们需要一些配置,在偏离标准时可能会有陷阱,但最终是可以做到的。
As always, all the code is available over on GitHub.
像往常一样,所有的代码都可以在GitHub上找到。