首页 > 解决方案 > Spring boot: how to correctly configure and use multiple datasources

问题描述

I am trying to setup multiple datasources correctly in Spring Boot with JPA 2.1.4.RELEASE. Setup is something like below:

So far I have successfully completed DEV setup. I have 2 configurations:

  1. for DB1
  2. for DB2

Then I have 2 Repos:

  1. for ABC which writes in DB1
  2. for XYZ which writes in DB2

Now in PROD, I need to write data in both servers(PROD1 and 2) in single transaction using spring boot.

I can see one example here which try to provide some sort of solution, but problem is it will ask to create duplicate Dao and Service class, which I think is not a good way of solving this problem and need to understand how to properly configure those properties in application.properties and DataSourceConfig.java

application-dev.properties

datasource.db1.url=jdbc:sqlserver://localhost:1234;databaseName=db1;
datasource.db1.username=user
datasource.db1.password=pwd
datasource.db1.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

datasource.db2.url=jdbc:sqlserver://localhost:1234;databaseName=db2;
datasource.db2.username=user
datasource.db2.password=pwd
datasource.db2.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

application-prod.properties

datasource.prod1.db1.url=jdbc:sqlserver://prodserver1:1234;databaseName=db1;
datasource.prod1.db1.username=user
datasource.prod1.db1.password=pwd
datasource.prod1.db1.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

datasource.prod1.db2.url=jdbc:sqlserver://prodserver1:1234;databaseName=db2;
datasource.prod1.db2.username=user
datasource.prod1.db2.password=pwd
datasource.prod1.db2.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

datasource.prod2.db1.url=jdbc:sqlserver://prodserver2:1234;databaseName=db1;
datasource.prod2.db1.username=user
datasource.prod2.db1.password=pwd
datasource.prod2.db1.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

datasource.prod2.db2.url=jdbc:sqlserver://prodserver2:1234;databaseName=db2;
datasource.prod2.db2.username=user
datasource.prod2.db2.password=pwd
datasource.prod2.db2.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver

Db1DataSourceConfig.java

@Configuration
@EnableJpaRepositories(
        basePackages = "demo.repos.db1",
        entityManagerFactoryRef = "db1EntityManagerFactory",
        transactionManagerRef = "db1TransactionManager")
public class Db1DataSourceConfig {
    @Autowired
    private Environment env;

    @Bean
    @ConfigurationProperties(prefix="datasource.db1")
    public DataSourceProperties db1DataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    public DataSource db1DataSource() {
        DataSourceProperties dataSourceProperties = db1DataSourceProperties();
        return DataSourceBuilder.create()
                .driverClassName(dataSourceProperties.getDriverClassName())
                .url(dataSourceProperties.getUrl())
                .username(dataSourceProperties.getUsername())
                .password(dataSourceProperties.getPassword())
                .build();
    }

    @Bean
    public PlatformTransactionManager db1TransactionManager() {
        EntityManagerFactory factory = db1EntityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean db1EntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(db1DataSource());
        factory.setPackagesToScan(new String[]{"demo.entities.db1"});
        factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql"));
        factory.setJpaProperties(jpaProperties);

        return factory;
    }
}

Db2DataSourceConfig.java

@Configuration
@EnableJpaRepositories(
        basePackages = "demo.repos.db2",
        entityManagerFactoryRef = "db2EntityManagerFactory",
        transactionManagerRef = "db2TransactionManager")
public class Db2DataSourceConfig {
    @Autowired
    private Environment env;

    @Bean
    @ConfigurationProperties(prefix="datasource.db2")
    public DataSourceProperties db2DataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    public DataSource db2DataSource() {
        DataSourceProperties dataSourceProperties = db2DataSourceProperties();
        return DataSourceBuilder.create()
                .driverClassName(dataSourceProperties.getDriverClassName())
                .url(dataSourceProperties.getUrl())
                .username(dataSourceProperties.getUsername())
                .password(dataSourceProperties.getPassword())
                .build();
    }

    @Bean
    public PlatformTransactionManager db2TransactionManager() {
        EntityManagerFactory factory = db2EntityManagerFactory().getObject();
        return new JpaTransactionManager(factory);
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean db2EntityManagerFactory() {
        LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
        factory.setDataSource(db2DataSource());
        factory.setPackagesToScan(new String[]{"demo.entities.db2"});
        factory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());

        Properties jpaProperties = new Properties();
        jpaProperties.put("hibernate.show_sql", env.getProperty("spring.jpa.show-sql"));
        factory.setJpaProperties(jpaProperties);

        return factory;
    }
}

标签: javaspring-bootspring-data-jpadatasource

解决方案


推荐阅读