linghu
linghu

Reputation: 133

spring boot hibernate auto create table with multi datasources

I met a problem when using multi datasources. I extends AbstractRoutingDataSource and create it as bean.like this:

@Configuration
public class JpaConfiguration{
    @Bean
    public void DataSource dataSource(){
        return new AbstractRoutingDataSource(){...}
    }

in my yml file,I set spring.jpa.hibernate.ddl-auto update.

spring:
    ...
    jpa:
        hibernate:
            ddl-auto: update
    ...

everything gone right. but when I change dataSource, like another schema.I must create tables myself.when I change dataSource or add dataSource into my routingDataSource runtime, is there any way to let hibernate auto create tables?

-----update---- spring boot auto create LocalContainerEntityManagerFactoryBean,and when application start,it use defaultDataSource, here is code in AbstractRoutingDataSource:

protected DataSource determineTargetDataSource() {
    Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");
    Object lookupKey = determineCurrentLookupKey();
    DataSource dataSource = this.resolvedDataSources.get(lookupKey);
    if (dataSource == null && (this.lenientFallback || lookupKey == null)) {
        dataSource = this.resolvedDefaultDataSource;
    }
    if (dataSource == null) {
        throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");
    }
    return dataSource;
}

With default dataSource ,hibernate auto create tables.but when I use another dataSource, it doesn't works.

Upvotes: 1

Views: 2174

Answers (2)

Claudiu
Claudiu

Reputation: 31

The trick for me was setting the em properties like this:

properties.put("hibernate.hbm2ddl.auto", "create-drop");
properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");

In my case, I was using H2, so you can replace the Dialect with whatever db you are using.

You can find the whole context of the configuration file below:

@Configuration
@PropertySource({"classpath:application.properties"})
@EnableJpaRepositories(
        basePackages = "com.spring.boot.repository.h2",
        entityManagerFactoryRef = "h2EntityManager",
        transactionManagerRef = "h2TransactionManager"
)
public class H2PersistenceConfiguration {

    @Autowired
    private Environment env;

    @Primary
    @Bean
    @ConfigurationProperties(prefix="spring.datasource")
    public DataSource h2DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean h2EntityManager() {
        final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(h2DataSource());
        em.setPackagesToScan("com.spring.boot.model.h2");

        final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        final HashMap<String, Object> properties = new HashMap<String, Object>();
        properties.put("hibernate.hbm2ddl.auto", "create-drop");
        properties.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
        em.setJpaPropertyMap(properties);

        return em;
    }

    @Primary
    @Bean
    public PlatformTransactionManager h2TransactionManager() {
        final JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(h2EntityManager().getObject());
        return transactionManager;
    }
}

Upvotes: 3

Mạnh Quyết Nguyễn
Mạnh Quyết Nguyễn

Reputation: 18235

To use custom datasource, you must tell your EntityManager to load JPA properties:

@Bean
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory(EntityManagerFactoryBuilder builder, 
                    DataSource dataSource, 
                    JpaProperties jpaProperties) {
    return builder
            .dataSource(dataSource)
            .packages(YourEntity.class)
            .persistenceUnit("yourEmName")
            // Important. load properties
            .properties(jpaProperties.getHibernateProperties(dataSource))
            .build();
}

Upvotes: 0

Related Questions