【问题标题】:spring boot hibernate auto create table with multi datasourcesspring boot hibernate 自动创建具有多数据源的表
【发布时间】:2019-01-21 22:55:21
【问题描述】:

我在使用多数据源时遇到了问题。我扩展 AbstractRoutingDataSource 并将其创建为 bean。像这样:

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

在我的 yml 文件中,我设置了 spring.jpa.hibernate.ddl-auto update。

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

一切顺利。但是当我更改数据源时,就像另一个架构一样。我必须自己创建表。当我更改数据源或将数据源添加到我的routingDataSource 运行时,有什么方法可以让休眠自动创建表?

-----更新---- spring boot 自动创建LocalContainerEntityManagerFactoryBean,应用启动时使用defaultDataSource,这里是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;
}

使用默认数据源,休眠自动创建表。但是当我使用另一个数据源时,它不起作用。

【问题讨论】:

    标签: hibernate spring-boot spring-data-jpa


    【解决方案1】:

    要使用自定义数据源,您必须告诉 EntityManager 加载 JPA 属性:

    @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();
    }
    

    【讨论】:

    • spring boot auto create LocalContainerEntityManagerFactoryBean,我只是用我的routingDataSource替换了默认的dataSource bean。
    • 默认数据源 + 默认 EM 已由 Boot 正确配置。要使用自定义数据源,您必须自己配置以下内容:连接池、附加 JPA 属性、事务管理器。
    【解决方案2】:

    对我来说,诀窍是像这样设置 em 属性:

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

    就我而言,我使用的是 H2,因此您可以将 Dialect 替换为您正在使用的任何数据库。

    您可以在下面找到配置文件的整个上下文:

    @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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-15
      • 2018-12-30
      • 1970-01-01
      • 2014-04-10
      • 2012-10-18
      • 2016-09-03
      • 2016-08-27
      • 2014-12-06
      相关资源
      最近更新 更多