Перейти к основному содержимому

Настройка и использование нескольких источников данных в Spring Boot

· 4 мин. чтения

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 .