Java Spring Boot从错误的数据源自动生成表

Java Spring Boot从错误的数据源自动生成表,java,spring-boot,jpa,spring-data-jpa,Java,Spring Boot,Jpa,Spring Data Jpa,我当前的项目需要连接到多个数据库。我设定 spring.jpa.generate-ddl=true spring.jpa.hibernate.ddl-auto=update 在application.properties中 我有一些dbConfig,如下所示: @Configuration public class DBSourceConfiguration { public final static String DATA_SOURCE_PRIMARY = "dataSource";

我当前的项目需要连接到多个数据库。我设定

spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
在application.properties中

我有一些dbConfig,如下所示:

@Configuration
public class DBSourceConfiguration {
    public final static String DATA_SOURCE_PRIMARY = "dataSource";
    public final static String DATA_SOURCE_PROPERTIES = "propertiesDataSource";
    public final static String DATA_SOURCE_REPORT = "reportDataSource";
    public final static String DATA_SOURCE_NEW_DRAGON = "newDragonDataSource";

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

    @Bean(name = DATA_SOURCE_REPORT)
    @ConfigurationProperties(prefix = "externaldatasource.report")
    public DataSource reportDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = DATA_SOURCE_NEW_DRAGON)
    @ConfigurationProperties(prefix = "externaldatasource.newdragon")
    public DataSource newDragonDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = DATA_SOURCE_PROPERTIES)
    @ConfigurationProperties(prefix = "externaldatasource.properties")
    public DataSource propertiesDataSource() {
        return DataSourceBuilder.create().build();
    }
}

还有两个DBConfig类,就像上面的两个DBConfig类一样

我的问题是每次运行这个web应用程序时,不同包下的实体都会生成到所有数据库。换句话说,Tbs的sPrimary实体将为newDragon和所有其他数据库生成表

例如,实体A属于主数据源,实体B属于properties datasouce。但框架生成表A、B到主数据库和newDragon数据库以及其他两个数据库

更新2018/06/01-1 虽然框架生成所有数据库的所有实体,但我仍然可以从正确的数据库访问表。我所有的web应用程序功能都工作得很好。这很奇怪,不是吗


我想我的配置很好,这样当我的应用程序访问数据库时就不会出现任何问题,比如从错误的数据库读取数据并获取空结果或将数据插入错误的数据库等。可能是其他原因导致了此问题。

基于您提供的配置,来自正确数据库的CRUD表应该不会有问题。但是在将表生成到正确的数据库中时,有时您可能需要检查配置是否正确选择了实体/包名称

每个LocalContainerEntityManagerFactoryBean都设置了唯一的包类,然后框架将扫描该包名下的实体,并在目标数据源上相应地生成表;但是,有一种情况是,packageToScan将被更改。因为您有@EntityScan注释,所以 在所有已定义的LocalContainerEntityManagerFactoryBean上重写PackageScon,参考代码如下:EntityScanRegistrar.java

因此,即使您为每个LocalContainerEntityManagerFactoryBean提供了唯一的包类,如果您在应用程序的某个地方安装了@EntityScan,那么最终结果仍可能被框架覆盖。在我看来,您的配置还可以,所以首先尝试查找并解决@EntityScan和LocalContainerEntityManagerFactoryBean之间的包名,它应该可以解决这个问题


参考:

您可以定义模式@Tableschema=schemaName@Eugen我已经试过了,但是我会得到一些错误,比如没有这样的模式或者类似的东西。框架似乎仍在尝试为所有数据库生成表。本文解释了如何配置:@Eugen我看过这篇文章并尝试过,尽管我仍然有同样的问题。不过还是要感谢您的回复。这解决了我的问题,谢谢。我设置@EntityScanbasePackages=all entities的根包,以便它覆盖我在DbConfig中配置的所有LocalContainerEntityManagerFactoryBean
<!-- language: Java -->

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = PrimaryDbConfig.ENTITY_MANAGER_FACTORY, 
            transactionManagerRef = PrimaryDbConfig.TRANSACTION_MANAGER, 
            basePackageClasses = { _TbsRepositoryBasePackage.class })
    public class PrimaryDbConfig extends AbstractDbConfig {
        public final static String ENTITY_MANAGER_FACTORY = "entityManagerFactoryPrimary";
        public final static String ENTITY_MANAGER = "entityManagerPrimary";
        public final static String TRANSACTION_MANAGER = "transactionManagerPrimary";

        @Autowired
        @Qualifier(DBSourceConfiguration.DATA_SOURCE_PRIMARY)
        private DataSource dataSource;

        @Primary
        @Bean(name = ENTITY_MANAGER_FACTORY)
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
            return builder.dataSource(dataSource).properties(getVendorProperties(dataSource)).packages(_TbsEntityBasePackage.class).persistenceUnit("primaryPersistenceUnit").build();
        }

        @Primary
        @Bean(name = ENTITY_MANAGER)
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactory(builder).getObject().createEntityManager();
        }

        @Primary
        @Bean(name = TRANSACTION_MANAGER)
        public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactory(builder).getObject());
        }    
    }
<!-- language: Java -->

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
            entityManagerFactoryRef = PropertiesDbConfig.ENTITY_MANAGER_FACTORY, 
            transactionManagerRef = PropertiesDbConfig.TRANSACTION_MANAGER, 
            basePackageClasses = { _PropertiesRepositoryBasePackage.class })
    public class PropertiesDbConfig extends AbstractDbConfig {
        public final static String ENTITY_MANAGER_FACTORY = "entityManagerFactoryProperties";
        public final static String ENTITY_MANAGER = "entityManagerProperties";
        public final static String TRANSACTION_MANAGER = "transactionManagerProperties";

        @Autowired
        @Qualifier(DBSourceConfiguration.DATA_SOURCE_PROPERTIES)
        private DataSource dataSource;

        @Bean(name = ENTITY_MANAGER_FACTORY)
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(EntityManagerFactoryBuilder builder) {
            return builder.dataSource(dataSource).properties(getVendorProperties(dataSource)).packages(_PropertiesEntityBasePackage.class).persistenceUnit("propertiesPersistenceUnit").build();
        }

        @Bean(name = ENTITY_MANAGER)
        public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
            return entityManagerFactory(builder).getObject().createEntityManager();
        }

        @Bean(name = TRANSACTION_MANAGER)
        public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
            return new JpaTransactionManager(entityManagerFactory(builder).getObject());
        }
    }
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    if (bean instanceof LocalContainerEntityManagerFactoryBean) {
        LocalContainerEntityManagerFactoryBean factoryBean = (LocalContainerEntityManagerFactoryBean) bean;
        factoryBean.setPackagesToScan(this.packagesToScan);
        this.processed = true;
    }
    return bean;
}