3.0 / 5
En las aplicaciones a nivel empresarial, es común tener múltiples bases de datos. Esto puede deberse a varias razones, como separar las operaciones de lectura y escritura, manejar sistemas heredados, entre otras. Con algunos ajustes de configuración, Spring Boot simplifica el proceso de configurar múltiples fuentes de datos en la aplicación. En este tutorial, vamos a profundizar en esta configuración de múltiples fuentes de datos.
Una aplicación Spring Boot necesita leer datos de una base de datos MySQL de solo lectura, procesar los datos y escribirlos en una PostgresDB. Aquà configuraremos estas dos fuentes de datos en nuestra aplicación Spring Boot.
Antes de entrar en el proceso, asegurémonos de cumplir con los siguientes requisitos previos:
Para este tutorial, vamos a usar JPA para interactuar con las fuentes de datos. Asà que añade Spring Data JPA starter como una dependencia. Además, necesitamos las dependencias de Postgres y MySQL para las fuentes de datos.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>{última versión aquÃ}</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>{última versión aquÃ}</version>
</dependency>
Code language: YAML (yaml)
En una configuración de fuente de datos única, añadimos la siguiente configuración al archivo application.properties
:
# DataSource
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=usuario
spring.datasource.password=contraseña
spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver
Code language: YAML (yaml)
Durante el inicio, la auto-configuración de Spring crea una instancia de org.springframework.boot.autoconfigure.jdbc.DataSourceProperties
y asigna estas configuraciones a los campos de DataSourceProperties
.
La anotación @ConfigurationProperties
en Spring Boot se usa para vincular propiedades externas (generalmente definidas en archivos application.properties
o application.yml
) a un objeto Java.
Para configurar múltiples fuentes de datos, necesitamos definir ambas configuraciones en el archivo application.properties
de la siguiente manera:
# Primera Fuente de Datos
spring.datasource.first.url=jdbc:mysql://localhost:3306/readingdb
spring.datasource.first.username=usuario
spring.datasource.first.password=contraseña
spring.datasource.first.driverClassName=com.mysql.cj.jdbc.Driver
# Segunda Fuente de Datos
spring.datasource.second.url=jdbc:postgresql://localhost:5432/writingdb
spring.datasource.second.username=usuario
spring.datasource.second.password=contraseña
spring.datasource.second.driverClassName=org.postgresql.Driver
Code language: YAML (yaml)
Para vincular las propiedades externas de ambas fuentes de datos, necesitamos usar @ConfigurationProperties
.
@Configuration
public class WritingDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.second")
public DataSourceProperties writingDataSourceProperties() {
return new DataSourceProperties();
}
}
@Configuration
public class ReadingDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.first")
public DataSourceProperties readingDataSourceProperties() {
return new DataSourceProperties();
}
}
Code language: Java (java)
En el paso 2, hemos mapeado con éxito las propiedades de ambas fuentes de datos a DataSourceProperties
. Ahora, vamos a crear las fuentes de datos utilizando estas propiedades.
@Configuration
public class WritingDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.second")
public DataSourceProperties writingDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
public DataSource writingDataSource() {
return writingDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
}
Code language: Java (java)
De manera similar, crea configuraciones para la segunda fuente de datos:
@Configuration
public class ReadingDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.first")
public DataSourceProperties readingDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
public DataSource readingDataSource() {
return readingDataSourceProperties()
.initializeDataSourceBuilder()
.build();
}
}
Code language: Java (java)
La necesidad de la anotación @Primary
en el bean readingDatasource
se explicará en la siguiente sección.
Para usar Spring Data JPA, necesitamos declarar las fábricas de EntityManager
para ambas fuentes de datos. Esta declaración especificará:
Por ejemplo, observa la configuración ReadingDataSourceJPAConfig
:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.readingdb.repository",
entityManagerFactoryRef = "readingEntityManagerFactory",
transactionManagerRef = "readingTransactionManager"
)
public class ReadingDataSourceJPAConfig {
@Bean
public LocalContainerEntityManagerFactoryBean readingEntityManagerFactory(
@Qualifier("readingDataSource") DataSource dataSource,
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource)
.packages("com.example.readingdb.model")
.build();
}
@Bean
public PlatformTransactionManager readingTransactionManager(
@Qualifier("readingEntityManagerFactory") LocalContainerEntityManagerFactoryBean readingEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(readingEntityManagerFactory.getObject()));
}
}
Code language: Java (java)
El EntityManagerFactoryBuilder
en el bean readingEntityManagerFactory
espera solo una fuente de datos durante la inyección de la fuente de datos (org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration
). Por lo tanto, necesitamos especificar una de las fuentes de datos como primaria usando la anotación @Primary
. De ahà que el readingDataSource
en el paso anterior fue hecho primario.
De manera similar, crea una configuración JPA para la segunda fuente de datos:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.example.writingdb.repository",
entityManagerFactoryRef = "writingEntityManagerFactory",
transactionManagerRef = "writingTransactionManager"
)
public class WritingDataSourceJPAConfig {
@Bean
public LocalContainerEntityManagerFactoryBean writingEntityManagerFactory(
@Qualifier("writingDataSource") DataSource dataSource,
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(dataSource)
.packages("com.example.writingdb.model")
.build();
}
@Bean
public PlatformTransactionManager writingTransactionManager(
@Qualifier("writingEntityManagerFactory") LocalContainerEntityManagerFactoryBean writingEntityManagerFactory) {
return new JpaTransactionManager(Objects.requireNonNull(writingEntityManagerFactory.getObject()));
}
}
Code language: Java (java)
¡Eso es todo, amigos! Hemos configurado con éxito una aplicación Spring Boot con múltiples fuentes de datos. Al iniciar, deberÃamos ver la configuración de ambas fuentes de datos en los registros como este:
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Starting...
com.zaxxer.hikari.pool.HikariPool : HikariPool-1 - Added connection com.mysql.cj.jdbc.ConnectionImpl@1da4b3f9
com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Start completed.
com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Starting...
com.zaxxer.hikari.pool.HikariPool : HikariPool-2 - Added connection org.postgresql.jdbc.PgConnection@28daf506
com.zaxxer.hikari.HikariDataSource : HikariPool-2 - Start completed.
Code language: YAML (yaml)
Podemos proceder con la configuración de la entidad y el repositorio desde aquÃ.
Puedes encontrar el código para esta demostración aquÃ: Repositorio de GitHub. He añadido un docker-compose
con dos bases de datos para una fácil ejecución.
Mantente feliz, sigue codificando.
Fuente aquÃ.