1. Обзор
Типичным сценарием для приложения Spring Boot является хранение данных в одной реляционной базе данных. Но иногда нам нужно получить доступ к нескольким базам данных.
В этом руководстве мы узнаем, как настроить и использовать несколько источников данных с Spring Boot. Чтобы узнать, как работать с одним источником данных, мы могли прочитать статью о введении в Spring Data JPA .
2. Поведение по умолчанию
Мы знаем, что объявление источника данных в Spring Boot выглядит так же, как в application.yml
:
spring:
datasource:
url: ...
username: ...
password: ...
driverClassname: ...
Внутри Spring сопоставляет эти параметры с экземпляром org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
. Давайте посмотрим на реализацию:
@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;
// ...
}
Мы должны указать на аннотацию @ConfigurationProperties
, которая автоматически сопоставляет свойства конфигурации с объектом Java.
3. Расширение значений по умолчанию
Итак, чтобы использовать несколько источников данных, нам нужно объявить несколько bean-компонентов с разными сопоставлениями в контексте приложения Spring.
Мы можем сделать это с помощью класса конфигурации:
@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();
}
}
Конфигурация источников данных должна выглядеть следующим образом:
spring:
datasource:
todos:
url: ...
username: ...
password: ...
driverClassName: ...
topics:
url: ...
username: ...
password: ...
driverClassName: ...
Затем мы можем создать источники данных с помощью объектов DataSourceProperties :
@Bean
public DataSource todosDataSource() {
return todosDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
@Bean
public DataSource topicsDataSource() {
return topicsDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
4. Весенние данные JDBC
При использовании Spring Data JDBC нам также необходимо настроить один экземпляр 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);
}
Затем мы также можем использовать их, указав @Qualifier
:
@Autowired
@Qualifier("topicsJdbcTemplate")
JdbcTemplate jdbcTemplate;
5. Спринг-данные JPA
При использовании Spring Data JPA мы хотим использовать такие репозитории, где Todo
— это сущность:
public interface TodoRepository extends JpaRepository<Todo, Long> {}
Поэтому нам нужно объявить фабрики 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()));
}
}
Мы должны знать о следующих ограничениях.
Нам нужно разделить пакеты, чтобы разрешить по одному @EnableJpaRepositories
для каждого источника данных.
К сожалению, чтобы внедрить EntityManagerFactoryBuilder
, нам нужно объявить один из источников данных как @Primary
. Это связано с тем, что EntityManagerFactoryBuilder
объявлен в org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration,
и этому классу требуется один внедренный источник данных. Как правило, некоторые части платформы могут не ожидать настройки нескольких источников данных.
6. Настройте пул соединений Hikari
Если мы хотим настроить Hikari , нам просто нужно добавить @ConfigurationProperties
в определение источника данных:
@Bean
@ConfigurationProperties("spring.datasource.todos.hikari")
public DataSource todosDataSource() {
return todosDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
Затем мы можем вставить следующие строки в файл application.properties :
spring.datasource.todos.hikari.connectionTimeout=30000
spring.datasource.todos.hikari.idleTimeout=600000
spring.datasource.todos.hikari.maxLifetime=1800000
7. Заключение
В этой статье мы узнали, как настроить несколько источников данных с помощью Spring Boot. Мы видели, что нам нужна некоторая конфигурация и что могут быть ловушки при отклонении от стандарта, но, наконец, мы видим, что это возможно.
Как всегда, весь код доступен на GitHub .