También tuve que configurar la conexión a 2 fuentes de datos desde la aplicación Spring Boot, y no fue fácil: la solución mencionada en la documentación de Spring Boot no funcionó. Después de una larga búsqueda en Internet, lo hice funcionar y la idea principal fue tomada de este artículo y de muchos otros lugares.
La siguiente solución está escrita en Kotlin y funciona con Spring Boot 2.1.3 e Hibernate Core 5.3.7 . El problema principal era que no bastaba con configurar diferentes configuraciones de DataSource , sino que también era necesario configurar EntityManagerFactory y TransactionManager para ambas bases de datos.
Aquí está la configuración para la primera base de datos (Primaria):
@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "firstDbEntityManagerFactory",
transactionManagerRef = "firstDbTransactionManager",
basePackages = ["org.path.to.firstDb.domain"]
)
@EnableTransactionManagement
class FirstDbConfig {
@Bean
@Primary
@ConfigurationProperties(prefix = "spring.datasource.firstDb")
fun firstDbDataSource(): DataSource {
return DataSourceBuilder.create().build()
}
@Primary
@Bean(name = ["firstDbEntityManagerFactory"])
fun firstDbEntityManagerFactory(
builder: EntityManagerFactoryBuilder,
@Qualifier("firstDbDataSource") dataSource: DataSource
): LocalContainerEntityManagerFactoryBean {
return builder
.dataSource(dataSource)
.packages(SomeEntity::class.java)
.persistenceUnit("firstDb")
// Following is the optional configuration for naming strategy
.properties(
singletonMap(
"hibernate.naming.physical-strategy",
"org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl"
)
)
.build()
}
@Primary
@Bean(name = ["firstDbTransactionManager"])
fun firstDbTransactionManager(
@Qualifier("firstDbEntityManagerFactory") firstDbEntityManagerFactory: EntityManagerFactory
): PlatformTransactionManager {
return JpaTransactionManager(firstDbEntityManagerFactory)
}
}
Y esta es la configuración para la segunda base de datos:
@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "secondDbEntityManagerFactory",
transactionManagerRef = "secondDbTransactionManager",
basePackages = ["org.path.to.secondDb.domain"]
)
@EnableTransactionManagement
class SecondDbConfig {
@Bean
@ConfigurationProperties("spring.datasource.secondDb")
fun secondDbDataSource(): DataSource {
return DataSourceBuilder.create().build()
}
@Bean(name = ["secondDbEntityManagerFactory"])
fun secondDbEntityManagerFactory(
builder: EntityManagerFactoryBuilder,
@Qualifier("secondDbDataSource") dataSource: DataSource
): LocalContainerEntityManagerFactoryBean {
return builder
.dataSource(dataSource)
.packages(EntityFromSecondDb::class.java)
.persistenceUnit("secondDb")
.build()
}
@Bean(name = ["secondDbTransactionManager"])
fun secondDbTransactionManager(
@Qualifier("secondDbEntityManagerFactory") secondDbEntityManagerFactory: EntityManagerFactory
): PlatformTransactionManager {
return JpaTransactionManager(secondDbEntityManagerFactory)
}
}
Las propiedades de las fuentes de datos son así:
spring.datasource.firstDb.jdbc-url=
spring.datasource.firstDb.username=
spring.datasource.firstDb.password=
spring.datasource.secondDb.jdbc-url=
spring.datasource.secondDb.username=
spring.datasource.secondDb.password=
El problema con las propiedades era que tenía que definir jdbc-url en lugar de url porque de lo contrario tenía una excepción.
ps
También puede tener diferentes esquemas de nombres en sus bases de datos, que fue el caso para mí. Como Hibernate 5 no es compatible con todos los esquemas de nombres anteriores, tuve que usar la solución de esta respuesta , tal vez también ayude a alguien también.