1

I am trying to use 2 DB in my spring app. From the first I read data and in the second I save the data. The problem is that my second DB it is not constructed.

application.properties

fromDB.datasource.url=jdbc:h2:file:D:/test1/db1
fromDB.datasource.username=sa
fromDB.datasource.password=
fromDB.datasource.platform=h2
fromDB.datasource.driverClassName=org.h2.Driver

toDB.datasource.url=jdbc:h2:file:D:/test2/db2
toDB.datasource.username=sa
toDB.datasource.password=
toDB.datasource.platform=h2
toDB.datasource.driverClassName=org.h2.Driver

###
#   H2 Settings
###
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console
spring.h2.console.settings.trace=true
spring.h2.console.settings.web-allow-others=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
###
#   Hibernate Settings
###
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.use_sql_comments=false
spring.jpa.properties.hibernate.format_sql=true
spring.datasource.initialization-mode=always
spring.datasource.initialize=true
spring.jpa.generate-ddl=true

Config classes

@Configuration
@EnableJpaRepositories
(
    basePackages = "leadTime.service",
    entityManagerFactoryRef = "toEntityManager",
    transactionManagerRef = "toTransactionManager"
)
@EnableTransactionManagement
public class OracleToDbConfig {

@Autowired
private Environment env;

@Bean(name = "datasourceTo")
@ConfigurationProperties(prefix = "toDB.datasource")
public DataSource dataSourceTo() {
return DataSourceBuilder.create().build();
}

@Qualifier("datasourceTo")
@PersistenceContext(unitName = "toEm")
@Bean(name = "toEntityManager")
public LocalContainerEntityManagerFactoryBean toEntityManager() {
LocalContainerEntityManagerFactoryBean em
    = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSourceTo());
em.setPackagesToScan(
    new String[]{"leadTime.to"});
HibernateJpaVendorAdapter vendorAdapter
    = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
    env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
    env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);

return em;
}

@Bean(name = "toTransactionManager")
public PlatformTransactionManager toTransactionManager() {

JpaTransactionManager transactionManager
    = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
    toEntityManager().getObject());
return transactionManager;
}
}


@Configuration
@EnableTransactionManagement
@EnableJpaRepositories
(
    basePackages = "leadTime.service",
    entityManagerFactoryRef = "fromEntityManager",
    transactionManagerRef = "fromTransactionManager"
)
public class OracleFromDbConfig {

@Autowired
private Environment env;

@Primary
@Bean(name = "datasourceFrom")
@ConfigurationProperties(prefix = "fromDB.datasource")
public DataSource dataSourceFrom() {
return DataSourceBuilder.create().build();
}

@PersistenceContext(unitName = "fromEm")
@Bean(name = "fromEntityManager")
@Qualifier("datasourceFrom")
@Primary
public LocalContainerEntityManagerFactoryBean fromEntityManager() {
LocalContainerEntityManagerFactoryBean em
    = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSourceFrom());
em.setPackagesToScan(
    new String[]{"leadTime.from"});
HibernateJpaVendorAdapter vendorAdapter
    = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.hbm2ddl.auto",
    env.getProperty("hibernate.hbm2ddl.auto"));
properties.put("hibernate.dialect",
    env.getProperty("hibernate.dialect"));
em.setJpaPropertyMap(properties);

return em;
}

@Primary
@Bean(name = "fromTransactionManager")
public PlatformTransactionManager fromTransactionManager() {

JpaTransactionManager transactionManager
    = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(
    fromEntityManager().getObject());
return transactionManager;
}
}

MainApp

@EnableJpaRepositories("leadTime.service")
@EntityScan(basePackageClasses = {
ToRepository.class,
FromRepository.class
})
@SpringBootApplication
public class LeadTimeApplication implements CommandLineRunner {

 private final ToRepository toRepository;
 private final FromRepository fromRepository;
 @Qualifier("datasourceTo")
 @Autowired
 DataSource dataSourceTo;
 @Qualifier("datasourceFrom")
 @Autowired
 DataSource dataSourceFrom;
 private Logger LOG = LoggerFactory.getLogger("LeadTimeApplication");

 @Autowired
 public LeadTimeApplication(ToRepository toRepository, FromRepository 
fromRepository) {
this.toRepository = toRepository;
this.fromRepository = fromRepository;
}

public static void main(String[] args) {
SpringApplication.run(LeadTimeApplication.class, args);

}

@Transactional("fromTransactionManager")
public void insertDataIntoFromDB() throws SQLException {
TestDataFrom testDataFrom = new TestDataFrom();
testDataFrom.setId(1);
testDataFrom.setName("Test");
fromRepository.save(testDataFrom);

dataSourceFrom.getConnection().commit();
}

@Transactional("toTransactionManager")
public void insertDataIntoToDB() throws SQLException {

TestDataTo testDataTo = new TestDataTo();
testDataTo.setId(1);
testDataTo.setName("Tst");
toRepository.save(testDataTo);
dataSourceTo.getConnection().commit();
}

@Override
public void run(String... args) throws Exception {
insertDataIntoFromDB();
insertDataIntoToDB();

TestDataFrom dataFrom = fromRepository.findOne(1);
Iterable<TestDataFrom> allT = fromRepository.findAll();
LOG.info("TestDataFrom with ID 1: {}", dataFrom.getName());

TestDataTo dataTo = toRepository.findOne(1);
Iterable<TestDataTo> all = toRepository.findAll();
LOG.info("TestDataTo with ID 1: {}", dataTo.getName());


}
}

I have searched here ( the example is taken from one of this links) multiple datasources in Spring Boot application http://xantorohara.blogspot.com/2013/11/spring-boot-jdbc-with-multiple.html Spring Boot Multiple Datasource Spring Boot, Spring Data JPA with multiple DataSources and so on.. there are a lot of links and example but I am not able to find the solution. Maybe I understood wrong the idea of @Primary and @Qualifier I have tried to exclude the DataSourceAutoConfiguration.class but still nothing.

UPDATE: both DB are created but I have problems save in both of them, I have managed to save both entities only in one db. Following error:

Parameter 0 of constructor in leadTime.LeadTimeApplication 
required a bean named 'entityManagerFactory' that could not be found.

I tried to follow: http://roufid.com/spring-boot-multiple-databases-configuration/ and other many art, but I get from one error to another.

agata
  • 481
  • 2
  • 9
  • 29
  • How do you know that only the first one is created? What are you doing, what do you expect to happen, and what happens instead? – JB Nizet Sep 14 '18 at 14:06
  • I think that this [link](https://medium.com/@joeclever/using-multiple-datasources-with-spring-boot-and-spring-data-6430b00c02e7) can help you – Matheus Sep 14 '18 at 14:06
  • @JBNizet: I am expecting 2 folders in my D directory. And only one is created. Am I wrong that I am expecting o be 2 created? – agata Sep 14 '18 at 14:08
  • I don't know. Start using these datasources in your code, and see if it works fine. Surely just creating a directory is not what you actually want. If it doesn't work fine, then post what you did, what you expected to happen, and what happened instead. – JB Nizet Sep 14 '18 at 14:10
  • 1
    Your db is consctructed, you just have to access the H2 db from http://localhost:8080/h2-console. Inside the H2 Console, Copy and paste jdbc:h2:mem:test2 in the JDBC URL field. Leave the password field empty and click the connect button. – AchillesVan Sep 14 '18 at 14:30
  • If it's a Spring Boot app, you can use the Actuator Beans endpoint to see all bean definitions (URL is `/actuator/beans` by default). https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html – Mike Sep 14 '18 at 14:30
  • I have separated the configs in 2 classes and tried to write in both dbs, but no success, I was able to create the DB and without the configuration for entityManager both tables were created in one DB. I have followed a lot of links without success. I have run out of ideas..cannot see the problem – agata Sep 18 '18 at 12:40

0 Answers0