Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple data source and schema creation in Spring Boot

I'm using Spring Boot. I finally managed to setup two data sources, but now I'm facing another issue.

  1. with two data sources in place spring.jpa.hibernate.ddl-auto=create seems to stop working in my spring boot application, only spring.jpa.generate-ddl=true do the job now

  2. I can not manage to select the auto-creation strategy for each of the data sources. I would prefer to create the schema for data source one, and just use the created schema in second DB with data source two.

Any body have idea how to resolve any of these issues? Note I don't want to completely throw away the auto-config if possible. I don't even know yet, if hibernate is able to just initialize schema in one persistence unit.

application.properties

spring.datasource-internal.url=jdbc:hsqldb:mem:testdb spring.datasource-internal.username=sa spring.datasource-internal.password=sa spring.datasource-internal.driver-class-name=org.hsqldb.jdbcDriver spring.datasource-internal.jpa.database-platform=org.hibernate.dialect.HSQLDialect  spring.datasource-external.url=jdbc:hsqldb:mem:testexternal spring.datasource-external.username=sa spring.datasource-external.password=sa spring.datasource-external.driver-class-name=org.hsqldb.jdbcDriver spring.datasource-external.jpa.database-platform=org.hibernate.dialect.HSQLDialect  flyway.enabled=false spring.jpa.hibernate.ddl-auto=create spring.jpa.show-sql=true spring.jpa.generate-ddl=true 

DBInternalConfig

     @Configuration     @EnableTransactionManagement     @EnableJpaRepositories(basePackages = "cz.data.internal",             entityManagerFactoryRef = "internalEntityManagerFactory",             transactionManagerRef = "internalTransactionManager")     public class DBConfigInternal {           public static final String INTERNAL = "internal";          @Bean(name = "internalDataSource")         @Primary         @ConfigurationProperties(prefix = "spring.datasource-internal")         public DataSource internalDataSource() {             return DataSourceBuilder.create().build();         }          @Bean(name = "internalEntityManagerFactory")         @Primary         public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(                 EntityManagerFactoryBuilder builder) {             return builder                     .dataSource(internalDataSource())                     .packages("cz.data.internal.entity")                     .persistenceUnit(INTERNAL)                     .build();         }          @Bean(name = "internalTransactionManager")         @Primary         public PlatformTransactionManager internalTransactionManager() {             JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();             jpaTransactionManager.setDataSource(internalDataSource());             jpaTransactionManager.setPersistenceUnitName(INTERNAL);             return jpaTransactionManager;         }     } 

DBExternalConfig

     @Configuration     @EnableTransactionManagement     @EnableJpaRepositories(             basePackages = "cz.data.external",             entityManagerFactoryRef = "externalEntityManagerFactory",             transactionManagerRef = "externalTransactionManager")     public class DBConfigExternal {           public static final String EXTERNAL = "external";          @Bean(name = "externalDataSource")         @ConfigurationProperties(prefix = "spring.datasource-external")         public DataSource externalDataSource() {             return DataSourceBuilder.create().build();         }          @Bean(name = "externalEntityManagerFactory")         public LocalContainerEntityManagerFactoryBean externalEntityManagerFactory(                 EntityManagerFactoryBuilder builder) {             return builder                     .dataSource(externalDataSource())                     .packages("cz.data.external.entity")                     .persistenceUnit(EXTERNAL)                     .build();         }          @Bean(name = "externalTransactionManager")         public PlatformTransactionManager externalTransactionManager() {             JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();             jpaTransactionManager.setDataSource(externalDataSource());             jpaTransactionManager.setPersistenceUnitName(EXTERNAL);             return jpaTransactionManager;         }     } 

M.W.

like image 792
Zveratko Avatar asked Feb 02 '15 10:02

Zveratko


People also ask

Can spring boot have multiple data sources?

To make a spring boot application that can communicate with more than one database you need to define some configuration to let spring boot when to execute each source.

How do I set up multiple schemas in spring boot?

Until now with spring 4 and XML configuration I was able to only put the DB URL like: jdbc:mysql://180.179.57.114:3306/?zeroDateTimeBehavior=convertToNull and in the entity class specify the schema to use and thus able to connect to multiple schemas.

How we can configure multiple database in spring boot?

To connect multiple databases, each database should be configured in its own spring boot configuration file. Multiple data sources should be configured for multiple databases. For spring data classes and spring data JPA repositories, two separate java packages need be created.


1 Answers

spring.jpa.hibernate.ddl-auto=create has stopped working, not because you have two DataSources, but because your application's creating its own LocalContainerEntityManagerFactoryBeans. This has the effect of disabling the auto-configuration of a LocalContainerEntityManagerFactoryBean so you now have to configure it yourself.

You can configure the two entity managers to have different schema generation behaviour like this (the first's doing update, the second's doing create):

@Bean(name = "externalEntityManagerFactory") public LocalContainerEntityManagerFactoryBean externalEntityManagerFactory(         EntityManagerFactoryBuilder builder) {     Map<String, Object> properties = new HashMap<String, Object>();     properties.put("hibernate.hbm2ddl.auto", "update");     return builder             .dataSource(externalDataSource())             .packages("cz.data.external.entity")             .persistenceUnit(EXTERNAL)             .properties(properties)             .build(); }  @Bean(name = "internalEntityManagerFactory") @Primary public LocalContainerEntityManagerFactoryBean internalEntityManagerFactory(         EntityManagerFactoryBuilder builder) {     Map<String, Object> properties = new HashMap<String, Object>();     properties.put("hibernate.hbm2ddl.auto", "create");     return builder             .dataSource(internalDataSource())             .packages("cz.data.internal.entity")             .persistenceUnit(INTERNAL)             .properties(properties)             .build(); } 
like image 155
Andy Wilkinson Avatar answered Oct 05 '22 18:10

Andy Wilkinson