4

I have a spring boot app that connects to two databases. Everything works fine.

My package structure looks like the following

- db
  - bar
    - BarDbConfig.java
    - domain
      - BarModel.java
    - repo
      - BarRepo.java
  - foo
    - FooDbConfig.java
    - domain
      - FooModel.java
    - repo
      - FooRepo.java

application.properties

spring.jpa.database=default
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl

#first db
bar.datasource.jdbc-url=jdbc:h2:C:\\Project\\com.example\\db3.data
bar.datasource.username=admin
bar.datasource.password=admin
bar.datasource.driver-class-name=org.h2.Driver

#second db
foo.datasource.jdbc-url=jdbc:h2:C:\\Project\\com.example\\db2.data
foo.datasource.username=admin
foo.datasource.password=admin
foo.datasource.driver-class-name=org.h2.Driver

BarDbConfig.java

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "barEntityManagerFactory",
        transactionManagerRef = "barTransactionManager"
)
public class BarDbConfig {

    @Bean
    @Primary
    @ConfigurationProperties(prefix = "bar.datasource")
    public DataSource barDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean barEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("barDataSource") DataSource dataSource
    ) {
        return builder.dataSource(dataSource)
                .packages(BarDbConfig.class.getPackage().getName())
                .persistenceUnit("barPersistenceUnit")
                .build();
    }

    @Primary
    @Bean
    public PlatformTransactionManager barTransactionManager(
            @Qualifier("barEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

FooDbConfig.java

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "fooEntityManagerFactory",
        transactionManagerRef = "fooTransactionManager"
)
public class FooDbConfig {

    @Bean
    @ConfigurationProperties(prefix = "foo.datasource")
    public DataSource fooDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean fooEntityManagerFactory(
            EntityManagerFactoryBuilder builder,
            @Qualifier("fooDataSource") DataSource dataSource
    ) {
        return builder.dataSource(dataSource)
                .packages(FooDbConfig.class.getPackage().getName())
                .persistenceUnit("fooPersistenceUnit")
                .build();
    }

    @Bean
    public PlatformTransactionManager fooTransactionManager(
            @Qualifier("fooEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
        return new JpaTransactionManager(entityManagerFactory);
    }
}

However, I was wondering if all this boilerplate code was really necessary?

  • Isn't there any way to remove all the LocalContainerEntityManagerFactoryBean and PlatformTransactionManager stuff?
  • Is there any reason why it is necessary to provide all those explicit Qualifier-names?
  • Can't spring boot find and autoconfigure the datasources by it self??
  • What would be the absolute minimal code required to connect to two databases utilizing convention over configuration?
1
  • 'back in the day' this would all be done in XML. however to do what you need(Multiple Datasources)..you need the Annotations you are currently using.... Commented Feb 19, 2019 at 19:18

1 Answer 1

2

I'm just going to answer the one question you ask in the title and then again in the body of your question:

Can't spring boot find and autoconfigure the DataSources by itself?

99% of applications use one database and these cases it is pretty obvious what you want to happen and that's what Boot does for you.

If you have 2 databases in your application there are many questions that don't have reasonable default answers:

Which repositories should use which DataSource? Split by package? Have two repositories for each interface? Have a routing DataSource? By what criterium should it route the requests?

Do you want one transaction across multiple DataSources or separate ones? Or maybe both for different use cases?

Of course, Boot could pick one possible answer for all these questions but the result would be only helpful for a small subset of an already small group of developers. Therefore it isn't done.

Of course, if you find something that is almost always done in a certain way, I'm sure the Spring Boot developers appreciate a feature request.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your answer. So it's the shortest way of handeling multiple data sources. But still wondering why they did not implement this, cause the code I posted, is how all the tutorials are doing it. So propbably 99% of the people using multiple data sources are doing it like i do. But anyway, thank you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.