使用 Liquibase 通过 ORM 填充数据

Using Liquibase to populate data with ORM

我目前正在使用 Liquibase 创建数据库模式。这是一个使用休眠 ORM 的 spring 启动应用程序。

Liquibase 在应用程序启动之初、ORM 初始化之前更改数据库架构(以便 ORM 在初始化时查看正确的架构)。

但是在应用程序启动后我想 运行 Liquibase 第二次在 ORM 和 java 代码的帮助下填充数据库中的数据(使用 java变更集:Java code changeset in liquibase ).

使用 Liquibase 用 ORM 和 java 填充数据的原因是因为 Liquibase 在集群中正常工作(例如,如果我们同时启动了 3 个节点,则只有一个节点会填充数据).

是否有可能 运行 Liquibase 在“2 个阶段”?

第一次,在应用程序启动期间更新数据库架构,第二次,在应用程序启动后,使用 ORM 填充一些数据。我们需要从 java 代码中做到这一点。

以前在使用 Flyway 时,我们通过拥有 2 个 Flyway 实例来做到这一点,每个实例都有单独的更改,并且 运行在应用程序启动开始之前在 ORM 初始化之前设置第一个实例,在 ORM 之后设置第二个实例启动完成,初始化ORM。

以下解决方案似乎有效:

@Component
class LiquibaseOrmMigrationRunner(val dataSource: DataSource, val resourceLoader: ResourceLoader, val environment: Environment) :
    ApplicationListener<ContextRefreshedEvent> {

    override fun onApplicationEvent(event: ContextRefreshedEvent) {
        val isLiquibaseEnabled = environment.getProperty("spring.liquibase.enabled", Boolean::class.java, true)

        if (!isLiquibaseEnabled) {
            return
        }

        var liquibase: Liquibase? = null

        try {
            val changeLogFile = "classpath:/db/changelog/orm/db.changelog-master-orm.yaml"
            val connection = dataSource.connection
            val liquibaseConnection = JdbcConnection(connection)
            val database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(liquibaseConnection)
            database.databaseChangeLogTableName = "ORMDATABASECHANGELOG"
            database.databaseChangeLogLockTableName = "ORMDATABASECHANGELOGLOCK"
            val resourceAccessor = SpringResourceAccessor(resourceLoader)
            liquibase = Liquibase(changeLogFile, resourceAccessor, database)
            liquibase.update(Contexts(), LabelExpression())
        } catch (e: SQLException) {
            throw DatabaseException(e)
        } finally {
            if (liquibase != null) {
                liquibase.close()
            }
        }
    }
}

这会创建一个额外的 liquibase 实例,该实例在 spring 启动配置的默认实例之后运行。

要使用 orm 填充数据库,附加的 liquibase 实例会执行以下变更集

databaseChangeLog:
    - changeSet:
          id: initial_data
          author: author
          changes:
              -   customChange: { "class": "com.example.LiquibaseInitialDataMigrationOrm" }

自定义更改如下所示:

class LiquibaseInitialDataMigrationOrm : CustomTaskChange {

    override fun execute(database: Database?) {
        val initialDataService = SpringApplicationContextSingleton.getBean("initialDataService") as InitialDataService

        initialDataService.populateInitialData()
    }

    override fun getConfirmationMessage(): String {
        return "Initial Data Liquibase ORM Migration finished"
    }

    @Suppress("EmptyFunctionBlock")
    override fun setUp() {
    }

    @Suppress("EmptyFunctionBlock")
    override fun setFileOpener(resourceAccessor: ResourceAccessor?) {
    }

    override fun validate(database: Database?): ValidationErrors {
        return ValidationErrors()
    }
}

自定义更改使用包含 spring 应用程序上下文的单例