In our case, we also have two databases, both using JPA and repositories. However, they do use different repositories, but I think our approach should also work in your case. We define an EntityManagerFactory and a TransactionManager per database. I cannot confirm this works, but I believe it should.
Primary Datasource:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = {"ch.sac.data.primary.repository"},
entityManagerFactoryRef = "entityManagerFactory",
transactionManagerRef = "transactionManager")
public class ImporterPrimaryDataSourceConfiguration {
@Primary
@Bean(name = "dataSourceProperties")
@ConfigurationProperties("spring.datasource")
public DataSourceProperties dataSourceProperties() {
return new DataSourceProperties();
}
@Primary
@Bean(name = "primaryDataSource")
public DataSource dataSource(final DataSourceProperties dataSourceProperties) {
return dataSourceProperties
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
@Primary
@Bean
public Flyway primaryFlyway(
final DataSource dataSource,
@Value("${spring.flyway.locations}") final String[] flywayLocations,
@Value("${spring.flyway.validate-on-migrate:true}")
final boolean flywayValidateOnMigrate) {
final var flyway =
Flyway.configure()
.dataSource(dataSource)
.locations(flywayLocations)
.validateOnMigrate(flywayValidateOnMigrate)
.load();
flyway.migrate();
return flyway;
}
@Primary
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory(
final EntityManagerFactoryBuilder entityManagerFactoryBuilder,
final DataSource dataSource) {
final var jpaProperties =
Map.ofEntries(
Map.entry(
"hibernate.dialect",
"org.hibernate.spatial.dialect.postgis.PostgisDialect"));
return entityManagerFactoryBuilder
.dataSource(dataSource)
.packages("ch.sac.model.primary.entity")
.persistenceUnit("dataSource")
.properties(jpaProperties)
.build();
}
@Primary
@Bean
public PlatformTransactionManager transactionManager(
final EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Secondary Datasource (SQLite Database, created in-memory, adjust to your use-case):
@Configuration
@EnableJpaRepositories(
basePackages = {"ch.sac.data.sqlite.repository"},
entityManagerFactoryRef = "sqliteEntityManagerFactory",
transactionManagerRef = "sqliteTransactionManager")
public class ImporterSQLiteDataSourceConfiguration {
@Bean(name = "sqliteDBFilePath")
public String sqliteDBFilePath() throws IOException {
return TempFileManager.createEmptyTempFile("metadata.sqlite").toString();
}
@Bean(name = "sqliteDataSourceProperties")
public DataSourceProperties sqliteDataSourceProperties() {
return new DataSourceProperties();
}
@Bean(name = "sqliteDataSource")
public DataSource sqliteDataSource(
@Qualifier("sqliteDataSourceProperties")
final DataSourceProperties sqliteDataSourceProperties,
final String sqliteDBFilePath) {
return sqliteDataSourceProperties
.initializeDataSourceBuilder()
.driverClassName("org.sqlite.JDBC")
.url("jdbc:sqlite:" + sqliteDBFilePath)
.type(HikariDataSource.class)
.build();
}
@Bean
public Flyway sqliteFlyway(
@Qualifier("sqliteDataSource") final DataSource sqliteDataSource,
@Value("${sqlite.flyway.locations}") final String[] flywayLocations) {
final var flyway =
Flyway.configure().dataSource(sqliteDataSource).locations(flywayLocations).load();
flyway.migrate();
return flyway;
}
@Bean(name = "sqliteEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean sqliteEntityManagerFactory(
final EntityManagerFactoryBuilder sqliteEntityManagerFactoryBuilder,
@Qualifier("sqliteDataSource") final DataSource sqliteDataSource) {
final var sqliteJpaProperties =
Map.ofEntries(
Map.entry(
"hibernate.dialect", "org.sqlite.hibernate.dialect.SQLiteDialect"));
return sqliteEntityManagerFactoryBuilder
.dataSource(sqliteDataSource)
.packages("ch.sac.model.sqlite.entity")
.persistenceUnit("sqliteDataSource")
.properties(sqliteJpaProperties)
.build();
}
@Bean(name = "sqliteTransactionManager")
public PlatformTransactionManager sqliteTransactionManager(
@Qualifier("sqliteEntityManagerFactory")
final EntityManagerFactory sqliteEntityManagerFactory) {
return new JpaTransactionManager(sqliteEntityManagerFactory);
}
}