2

In this official example of configuring 2 data sources, they have used embedded DB. So, with the help of Spring boot's How to documentations, Configure Two DataSources and Using Multiple EntityManagerFactories, I customized that to use MySQL DB.

You can find the complete code under this Github repository. Don't forget to checkout the "two_data_sources_in_separate_files" branch.

But with this modification, "secondDBTransactionManager" is not pointing second_db. Instead, it is inserting data into first_db.

FirstDataSource.java

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "firstDBEntityManagerFactory", transactionManagerRef = "firstDBTransactionManager")

public class FirstDataSource {
@Bean
PlatformTransactionManager firstDBTransactionManager(DataSourceProperties firstDataSourceProperties) {
    return new JpaTransactionManager(firstDBEntityManagerFactory(firstDataSourceProperties).getObject());
}

@Bean
@Primary
LocalContainerEntityManagerFactoryBean firstDBEntityManagerFactory(DataSourceProperties firstDataSourceProperties) {

    HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
    jpaVendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

    factoryBean.setDataSource(firstDS(firstDataSourceProperties));
    factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
    factoryBean.setPackagesToScan(FirstDataSource.class.getPackage().getName());

    return factoryBean;
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.first")
public DataSourceProperties firstDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@Primary
@ConfigurationProperties("app.datasource.first.configuration")
public HikariDataSource firstDS(DataSourceProperties firstDataSourceProperties) {
    return firstDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

}

SecondDataSource.java

@Configuration
@EnableJpaRepositories(entityManagerFactoryRef = "secondDBEntityManagerFactory", transactionManagerRef = "secondDBTransactionManager")
public class SecondDataSource {

@Bean
PlatformTransactionManager secondDBTransactionManager(DataSourceProperties secondDataSourceProperties) {
    return new JpaTransactionManager(secondDBEntityManagerFactory(secondDataSourceProperties).getObject());
}

@Bean
@ConfigurationProperties("app.datasource.second")
public DataSourceProperties secondDataSourceProperties() {
    return new DataSourceProperties();
}

@Bean
@ConfigurationProperties("app.datasource.second.configuration")
public HikariDataSource secondDS(
        @Qualifier("secondDataSourceProperties") DataSourceProperties secondDataSourceProperties) {
    return secondDataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
}

@Bean
public LocalContainerEntityManagerFactoryBean secondDBEntityManagerFactory(DataSourceProperties secondDataSourceProperties) {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(true);

    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(secondDS(secondDataSourceProperties));
    factoryBean.setJpaVendorAdapter(vendorAdapter);
    factoryBean.setPackagesToScan(SecondDataSource.class.getPackage().getName());

    return factoryBean;
}

}

FetchData.java

@Controller // This means that this class is a Controller
@RequestMapping(path = "/demo") // This means URL's start with /demo (after Application path)
public class FetchData {

@Autowired
private TableARepository tableARepository;

@Autowired
private TableCRepository tableCRepository;

@GetMapping(path = "/addDataToFirstDB")
public @ResponseBody void addDataToFirstDB() {
    // This returns a JSON or XML with the users
    Table_A tableA = new Table_A();
    tableA.setTable_a_col_1("test1");
    tableA.setTable_a_col_2("test2");
    tableA.setTable_a_col_3("test3");
    tableA.setTable_a_col_4("test4");
    
    System.out.println("Inserting data into first DB.");
    tableARepository.save(tableA);
    
}

@GetMapping(path = "/addDataToSecondDB")
@Transactional("secondDBTransactionManager")
public @ResponseBody void addDataToSecondDB() {
    // This returns a JSON or XML with the users
    Table_C tableC = new Table_C();
    tableC.setTable_c_col_1("test1");
    tableC.setTable_c_col_2("test2");
    tableC.setTable_c_col_3("test3");
    tableC.setTable_c_col_4("test4");
    
    System.out.println("Inserting data into second DB.");
    tableCRepository.save(tableC);
}
}

Observe that, I've used @Transactional("secondDBTransactionManager") for second REST API, "addDataToSecondDB". It is easy to resolve issue if any Exception is thrown. There is no Exception here but the behavior is not as expected.

0

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.