【问题标题】:Can you initialize Spring Batch metadata tables with Liquibase?你能用 Liquibase 初始化 Spring Batch 元数据表吗?
【发布时间】:2020-03-08 16:22:36
【问题描述】:

目前我有如下设置。在本地运行批处理作业时,作业将使用data-source 属性值自动创建必要的元数据表,因为initialize-schema 设置为always。 Liquibase 还将运行并创建其更改日志中列出的任何表。

这是我的application.yml 文件

spring:
  batch:
    initialize-schema: always
    job:
      enabled: true
  liquibase:
    url: db_url
    user: deploy_user
    password: deploy_pass
    change-log: classpath:db/changelog/db.changelog-master.yaml
    enabled: true
data-source:
  mysql:
    user: r_user
    password: r_pass
    jdbc-url: db_url

这是我的db.changelog-master.yaml 文件。

databaseChangeLog:

  - changeSet:
    dbms: mysql
    id: create-sample-table
    author: me
    sql: CREATE TABLE sample_table (
      sample_id VARCHAR(255) NOT NULL,
      sample_text TEXT,
      PRIMARY KEY (samoke_id)
      ) ENGINE=InnoDB DEFAULT
      CHARSET=utf8 COLLATE=utf8_bin;

Mysql 数据源配置:

@Configuration
public class DataSourceConfiguration {

    @Primary
    @Bean(name = "mySQLDataSource")
    @ConfigurationProperties("data-source.mysql")
    public DataSource mySQLDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
}

Liquibase 配置(可能发布的内容超出了需要):

@Configuration
@EnableConfigurationProperties(LiquibaseProperties.class)
public class LiquibaseConfiguration {
    private static final Logger LOG = LoggerFactory.getLogger(LiquibaseConfiguration.class);

    @Autowired
    private LiquibaseProperties liquibaseProperties;


    public DataSource liquibaseDataSource() {
        DataSourceBuilder factory = DataSourceBuilder
                .create()
                .url(liquibaseProperties.getUrl())
                .username(liquibaseProperties.getUser())
                .password(liquibaseProperties.getPassword());

        return factory.build();
    }

    public void testLiquibaseConnection() throws SQLException {

        LOG.info("Testing connection to Liquibase (in case PCF restarts and we have stale dynamic secrets)...");
        liquibaseDataSource().getConnection();
        LOG.info("Testing connection to Liquibase (in case PCF restarts and we have stale dynamic secrets)... Succeeded");
    }

    @Bean
    public SpringLiquibase liquibase() {
        try {
            testLiquibaseConnection();
        } catch (Exception ex) {
            LOG.warn("WARNING: Could not connect to the database using " + liquibaseProperties.getUser() + ", so we will be skipping the Liquibase Migration for now. ", ex);
            return null;
        }
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setChangeLog(this.liquibaseProperties.getChangeLog());
        liquibase.setContexts(this.liquibaseProperties.getContexts());
        liquibase.setDataSource(liquibaseDataSource());
        liquibase.setDefaultSchema(this.liquibaseProperties.getDefaultSchema());
        liquibase.setDropFirst(this.liquibaseProperties.isDropFirst());
        liquibase.setShouldRun(this.liquibaseProperties.isEnabled());
        liquibase.setLabels(this.liquibaseProperties.getLabels());
        liquibase.setChangeLogParameters(this.liquibaseProperties.getParameters());
        return liquibase;
    }

}

问题是我们在已部署环境中创建/部署表和读取/写入表的凭据不同。因此,以下设置将通过 Liquibase 创建表,但由于部署时凭据不正确,无法创建元数据表。我们当前创建元数据表的解决方法是使用具有部署凭据的data-source 属性进行部署,运行作业以初始化表,然后使用读/写凭据重新部署。 (我们不能只将部署凭据留给读取,因为它们的 TTL 很短)。

是否可以通过 Liquibase 自动为 Spring Batch 创建元数据表?具体来说,无需手动将创建 SQL 添加到更改日志文件中?

更新:

使用下面 veljkost 的答案,有一个看起来像这样的变更日志文件:

databaseChangeLog:
  - changeSet:
      dbms: mysql
      id: create-spring-batch-metadata
      author: dev.me
      changes:
        - sqlFile:
            encoding: UTF-8
            path: classpath:/org/springframework/batch/core/schema-mysql.sql
            relativeToChangelogFile: false
            splitStatements: true
            stripComments: true

【问题讨论】:

  • the job will create the necessary metadata tables automatically:这不正确,Spring Batch 不会自动创建表,由您手动完成或告诉 Spring boot 为您完成(如您的情况)。您需要确保您的 liquibase 脚本在作业之前运行,以便 Spring Batch 可以找到表并报告其元数据。
  • 这可能只是我的措辞不当,对此我深表歉意,因为我已经 initialize-schema: always 设置了架构是在运行作业之前创建的。编辑了问题以使其更加明确。此外,liquibase 确实首先运行,主要问题是 liquibase 能否以某种方式创建这些元数据表,而无需在更改日志中明确显示它们。
  • 好的,感谢您的澄清。 the main question is can liquibase somehow create those metadata tables without them being explicitly in the changelog.:这是一个 liquibase 问题,而不是春季批处理问题。我对 liquibase 不太熟悉,所以我会让对此有更深入了解的人来回答您的问题。

标签: java spring spring-boot spring-batch liquibase


【解决方案1】:

是的,您可以引用 Spring Batch 项目中已经存在的架构文件。在org.springframework.batch.core 包中,您可以找到 schema-*.sql 文件,其中 * 是目标数据库的名称。由于您在 mysql 上运行,因此您的更改集将如下所示:

- changeSet:
  id: 1234
  author: adam.sandler
  changes:
      - sqlFile:
            encoding: utf8
            path: classpath:/org/springframework/batch/core/schema-mysql.sql
            relativeToChangelogFile: false
            splitStatements: true
            stripComments: true

【讨论】:

  • 啊,太棒了,感谢您指出这一点。我没有意识到你可以指定一个 sqlFile。
【解决方案2】:

在不使用 liquabase add 的情况下自动迁移到您的数据库

spring.batch.initialize-schema=always

到您的 application.properties 文件,它将自动迁移到嵌入式数据源

【讨论】:

  • 虽然这应该可行,但我们的目标是通过 liquibase 管理所有数据库架构以防止任何冲突。
猜你喜欢
  • 2019-03-08
  • 1970-01-01
  • 1970-01-01
  • 2020-07-17
  • 2014-02-06
  • 2013-11-26
  • 2010-11-15
  • 2019-10-23
  • 1970-01-01
相关资源
最近更新 更多