简体   繁体   English

Spring Boot 2多个数据源初始化架构

[英]Spring Boot 2 Multiple Datasources initialize schema

I have a Spring Boot 2 application that's using two datasources - one Oracle and one H2. 我有一个使用两个数据源的Spring Boot 2应用程序-一个Oracle和一个H2。 The H2 datasource is set up as secondary, and I want to create the schema for it upon startup, but it never fires off the schema.sql file. H2数据源设置为辅助数据源,我想在启动时为其创建架构,但是它永远不会触发schema.sql文件。 This is my Data Source Config file: 这是我的数据源配置文件:

@Configuration
public class DataSourceConfig {
    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    public DataSourceProperties primaryDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("spring.datasource")
    public DataSource primaryDataSource() {
        return primaryDataSourceProperties().initializeDataSourceBuilder().build();
    }

    @Bean
    @ConfigurationProperties("spring.runlogdatasource")
    public DataSourceProperties runlogDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("spring.runlogdatasource")
    public DataSource runlogDataSource() {
        return runlogDataSourceProperties().initializeDataSourceBuilder().build();
    }
}

This is my application.properties file: 这是我的application.properties文件:

spring.datasource.url=jdbc:oracle:thin:@my.database.com:1521/mydb
spring.datasource.username=test
spring.datasource.password=ENC(3PXcnoBndLpWN1EcMtmIn+odOwhdWjSrqANijutxuekKEIOco64Jew==)
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.initialization-mode=never
spring.datasource.hikari.connection-timeout=60000
spring.datasource.hikari.maximum-pool-size=10
jasypt.encryptor.bean=stringEncryptor
spring.runlogdatasource.url=jdbc:h2:~/runlogdb;CIPHER=AES;DB_CLOSE_ON_EXIT=FALSE;
spring.runlogdatasource.username=sa
spring.runlogdatasource.password=ENC(3PXcnoBndLpWN1EcMtmIn+odOwhdWjSrqANijutxuekKEIOco64Jew==)
spring.runlogdatasource.driverClassName=org.h2.Driver
spring.runlogdatasource.platform=h2
spring.runlogdatasource.schema=classpath:schema-h2.sql

For the primary datasource, I can see that it enters the DataSourceInitializerInvoker which is where it attempts to load up the schema, but since there are no schema-all.sql files it skips over that one. 对于主要数据源,我可以看到它进入了DataSourceInitializerInvoker,它是试图加载该架构的地方,但是由于没有schema-all.sql文件,它会跳过该数据库。 However, I do have a schema-h2.sql file, but for the secondary datasource it never enters the DataSourceInitializerInvoker and therefore never attempts to initialize the schema. 但是,我确实有一个schema-h2.sql文件,但是对于辅助数据源,它从不输入DataSourceInitializerInvoker,因此从不尝试初始化该模式。 Any help would be greatly appreciated! 任何帮助将不胜感激!

This is expected behaviour. 这是预期的行为。 When Primary datasource is specified only the schema and data for this datasource is executed. 指定主要数据源后,仅执行该数据源的架构和数据。 What you need to do in order to have this behavior is to define DataSourceInitializer for each of the two datasources. 为了具有此行为,您需要为两个数据DataSourceInitializer中的每一个定义DataSourceInitializer

        @Bean
        public DataSourceInitializer dataSourceInitializer1(@Qualifier("datasource1") DataSource datasource) {
            ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
            resourceDatabasePopulator.addScript(new ClassPathResource("schema-h22.sql"));
            resourceDatabasePopulator.addScript(new ClassPathResource("data-h22.sql"));

                DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
                dataSourceInitializer.setDataSource(datasource);
                dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
                return dataSourceInitializer;
        }

    @Bean
    public DataSourceInitializer dataSourceInitializer2(@Qualifier("datasource2") DataSource datasource) {
        ResourceDatabasePopulator resourceDatabasePopulator = new ResourceDatabasePopulator();
        resourceDatabasePopulator.addScript(new ClassPathResource("schema-h21.sql"));
        resourceDatabasePopulator.addScript(new ClassPathResource("data-h21.sql"));

            DataSourceInitializer dataSourceInitializer = new DataSourceInitializer();
            dataSourceInitializer.setDataSource(datasource);
            dataSourceInitializer.setDatabasePopulator(resourceDatabasePopulator);
            return dataSourceInitializer;
    }

You also need to disable the default spring data initialization. 您还需要禁用默认的spring数据初始化。 You can do this through spring.datasource.initialization-mode=never 您可以通过spring.datasource.initialization-mode=never来执行此spring.datasource.initialization-mode=never

You can use multiple Liquibase configuration corresponding to your datasources. 您可以使用与您的数据源相对应的多个Liquibase配置。 That could help you in initializing schema for both datasources 这可以帮助您初始化两个数据源的架构

Sample: - 范例:-

...

@Bean
@ConfigurationProperties(prefix = "spring.datasource.liquibase")
public LiquibaseProperties primaryLiquibaseProperties() {
    return new LiquibaseProperties();
}

@Bean
public SpringLiquibase primaryLiquibase() {
    return springLiquibase(primaryDataSource(), primaryLiquibaseProperties());
}
@Bean
@ConfigurationProperties(prefix = "spring.runlogdatasource.liquibase")
public LiquibaseProperties secondaryLiquibaseProperties() {
    return new LiquibaseProperties();
}

@Bean
public SpringLiquibase secondaryLiquibase() {
    return springLiquibase(secondaryDataSource(), secondaryLiquibaseProperties());
}

private static SpringLiquibase springLiquibase(DataSource dataSource, LiquibaseProperties properties) {
    SpringLiquibase liquibase = new SpringLiquibase();
    liquibase.setDataSource(dataSource);
    liquibase.setChangeLog(properties.getChangeLog());
    liquibase.setContexts(properties.getContexts());
    liquibase.setDefaultSchema(properties.getDefaultSchema());
    liquibase.setDropFirst(properties.isDropFirst());
    liquibase.setShouldRun(properties.isEnabled());
    liquibase.setLabels(properties.getLabels());
    liquibase.setChangeLogParameters(properties.getParameters());
    liquibase.setRollbackFile(properties.getRollbackFile());
    return liquibase;
}
...

U can edit your properties as following: U可以如下编辑属性:

 **spring.datasource.liquibase.change-log=** classpath:/db/changelog/db.primary.changelog-master.xml **spring.runlogdatasource.liquibase.change-log=** classpath:/db/changelog/db.secondary.changelog-master.xml 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM