I have spent some days trying to solve this error but without success. I am trying to configure two databases and write in both of them.
I looked at:
https://www.baeldung.com/spring-data-jpa-multiple-databases
https://www.devglan.com/spring-boot/spring-boot-multiple-database-configuration
https://github.com/igormukhin/spring-boot-sample-data-jpa-multiple/blob/master/src/main/java/sample/data/jpa/Database1Configuration.java And a loot more links from SO for the errors or similar examples.
Here is my code:
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
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 -hibernate.properties
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
ConfigClasses
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "toEntityManager",
transactionManagerRef = "toTransactionManager",
basePackages = "leadTime.service"
)
public class ToDBConfig {
@Bean
@ConfigurationProperties(prefix = "toDB.datasource")
public DataSource toDataSource() {
return DataSourceBuilder
.create()
.build();
}
@Bean(name = "toEntityManager")
public LocalContainerEntityManagerFactoryBean toEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(toDataSource())
.properties(hibernateProperties())
.packages(TestDataTo.class)
.persistenceUnit("to")
.build();
}
@Bean(name = "toTransactionManager")
public PlatformTransactionManager toTransactionManager(@Qualifier("toEntityManager") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
private Map hibernateProperties() {
Resource resource = new ClassPathResource("hibernate.properties");
try {
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
return properties.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue())
);
} catch (IOException e) {
return new HashMap();
}
}
}
Second configClass
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "fromEntityManager",
transactionManagerRef = "fromTransactionManager",
basePackages = "leadTime.service"
)
public class FromDBConfig {
@Primary
@Bean
@ConfigurationProperties(prefix = "fromDB.datasource")
public DataSource fromDataSource() {
return DataSourceBuilder
.create()
.build();
}
@Primary
@Bean(name = "fromEntityManager")
public LocalContainerEntityManagerFactoryBean fromEntityManagerFactory(
EntityManagerFactoryBuilder builder) {
return builder
.dataSource(fromDataSource())
.properties(hibernateProperties())
.packages(TestDataFrom.class)
.persistenceUnit("from")
.build();
}
@Primary
@Bean(name = "fromTransactionManager")
public PlatformTransactionManager fromTransactionManager(@Qualifier("fromEntityManager") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
private Map hibernateProperties() {
Resource resource = new ClassPathResource("hibernate.properties");
try {
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
return properties.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey().toString(),
e -> e.getValue())
);
} catch (IOException e) {
return new HashMap();
}
}}
Repository:
public interface ToRepository extends CrudRepository<TestDataTo, Integer>
{
@Override
TestDataTo save(TestDataTo testDataTo);
}
DataInit:
@Component
public class DataInit {
@Autowired
ToRepository toRepository;
@Autowired
FromRepository fromRepository;
@Transactional("fromTransactionManager")
public void insertDataIntoFromDB() throws SQLException {
TestDataFrom testDataFrom = new TestDataFrom();
testDataFrom.setId(1);
testDataFrom.setName("Test");
fromRepository.save(testDataFrom);
}
//
@Transactional("toTransactionManager")
public void insertDataIntoToDB() throws SQLException {
TestDataTo testDataTo = new TestDataTo();
testDataTo.setId(1);
testDataTo.setName("Ale");
toRepository.save(testDataTo);
}
}
MainClass:
@EnableTransactionManagement
@SpringBootApplication
public class LeadTimeApplication {
private Logger LOG = LoggerFactory.getLogger("LeadTimeApplication");
@Autowired
ToRepository toRepository;
@Autowired
FromRepository fromRepository;
public static void main(String[] args) {
SpringApplication.run(LeadTimeApplication.class, args);
}
@Autowired DataInit initializer;
@PostConstruct
public void init() throws SQLException{
initializer.insertDataIntoFromDB();
initializer.insertDataIntoToDB();
}
Error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Field toRepository in leadTime.LeadTimeApplication
required a bean named 'entityManagerFactory' that could not be found.
Action:
Consider defining a bean named 'entityManagerFactory' in your configuration.
I tried: Using
@EnableAutoConfiguration(exclude = { JpaRepositoriesAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class})
Honestly, I don't know what else to do, I re-wrote this code so many times using different approaches but without success. If I let spring to his job, without configuring new entityManagers and transactions and without using @Transactional
, the application is working (2 DBs are created), but both tables are created in the sameDB (of course)
Added gradle config
//Spring dependencies
compile "org.springframework.boot:spring-boot-starter-
actuator:${springBootVersion}"
compile "org.springframework.boot:spring-boot-starter-
web:${springBootVersion}"
compile "org.springframework.boot:spring-boot-starter-
logging:${springBootVersion}"
compile "org.springframework.boot:spring-boot-configuration-
processor:${springBootVersion}"
//JPA dependency
compile "org.springframework.boot:spring-boot-starter-data-
jpa:${springBootVersion}"
testCompile "com.oracle:ojdbc7:12.1.0.2"
testCompile 'com.h2database:h2:1.4.194'
runtime 'com.h2database:h2:1.4.194'
// compile group: 'h2', name: 'h2', version: '0.2.0'
compile group: 'org.hibernate', name: 'hibernate-entitymanager'
//compile group: 'org.hibernate', name: 'hibernate-gradle-plugin', version:
'5.3.6.Final'
// https://mvnrepository.com/artifact/org.hibernate/hibernate-core
compile group: 'org.hibernate', name: 'hibernate-core'