Skip to content

liquibase 数据库表版本管理

简介

risenet-y9boot-starter-liquibase 结合了 liquibase 及数字底座的数据源可实现对公共库和租户库的表结构版本管理。

公共库表结构管理需结合 risenet-y9boot-starter-jpa-public 组件使用,租户库表结构管理需结合多租户组件 risenet-y9boot-starter-multi-tenant 使用。

liquibase 可以使用 SQL, XML, JSON, YAML 等多种格式管理修改日志(changelog),修改日志最终可以转换成兼容的多种数据库语法执行。

liquibase 会生成两个表以追踪当前数据库表结构的版本

功能引用

接下来以 risenet-y9boot-server-platform 模块为例介绍 risenet-y9boot-starter-liquibase 的使用。

添加依赖

添加组件依赖包

xml
    <dependency>
        <groupId>net.risesoft</groupId>
        <artifactId>risenet-y9boot-starter-liquibase</artifactId>
        <version>[最新正式版本]</version>
    </dependency>
    <!-- 根据情况添加 risenet-y9boot-starter-jpa-public risenet-y9boot-starter-multi-tenant 依赖-->

如需使用 SNAPSHOT 版本,且 maven 没有 POM 继承链至数字底座的 y9-digitalbase-parent 则还需将有生的私服仓库地址添加到 pom.xml 文件中。

xml
<repositories>
    <repository>
        <id>y9-internet-repo</id>
        <url>https://svn.youshengyun.com:9900/nexus/repository/maven-public/</url>
        <releases>
            <enabled>true</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
            <!-- <updatePolicy>always</updatePolicy> -->
            <!-- always,daily(default),interval:XXX,never -->
        </snapshots>
    </repository>
</repositories>

修改配置文件

yaml
y9:
    feature:
        liquibase:
            tenant-enabled: true # 租户库使用 liquibase 进行版本管理
            public-enabled: true # 公共库使用 liquibase 进行版本管理
spring:
    jpa:
        hibernate:
            ddl-auto: none
properties
y9.feature.liquibase.tenant-enabled=true # 租户库使用 liquibase 进行版本管理
y9.feature.liquibase.public-enabled=true # 公共库使用 liquibase 进行版本管理
spring.jpa.hibernate.ddl-auto=none

注意: hibernate 虽然也有更新创建表结构的能力,但是不具备“数据库版本管理”的能力,不适合生产使用,使用 liquibase 时需先将其关闭,两者在功能上有冲突。

更多的配置属性可参考 y9-digitalbase-starter/risenet-y9boot-starter-liquibase/src/main/java/net/risesoft/y9/configuration/feature/liquibase/Y9LiquibaseProperties.java

编写 ChangeLog 文件

公共库及租户库的 changelog 默认路径分别为 classpath:/liquibase/public/main.xmlclasspath:/liquibase/tenant/main.xml

目录结构如下:

resources
└── liquibase
    ├── public
    │   ├── release
    │   │   └── ... // 各个版本增量的 ChangeLog
    │   ├── init.xml // 初始化 ChangeLog
    │   └── main.xml

    └── tenant
        ├── release
        │   └── ... // 各个版本增量的 ChangeLog
        ├── init.xml // 初始化 ChangeLog
        └── main.xml

以公共库的 main.xml 为例:

xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd">

    <!-- 引入具体的某个文件,文件中的 changeSet 按编写的顺序由上往下执行 -->
    <include file="liquibase/public/init.xml"/>
    <!-- 按字母表顺序引入目录下的所有文件 -->
    <includeAll path="liquibase/public/release/"/>

</databaseChangeLog>

公共库的 init.xml 部分内容,第一个 changeset 新增 Y9_PUBLISHED_EVENT_SYNC_HIST 表,后一个 changeset 创建表 Y9_COMMON_ACCOUNT 的索引

xml
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
                      http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.9.xsd"
        objectQuotingStrategy="QUOTE_ONLY_RESERVED_WORDS">

    <changeSet id="1697708034037-15" author="shidaobang" runOnChange="true">
        <preConditions onFail="MARK_RAN">
            <not>
                <tableExists tableName="Y9_PUBLISHED_EVENT_SYNC_HIST"/>
            </not>
        </preConditions>
        <createTable remarks="事件监听api获取记录表" tableName="Y9_PUBLISHED_EVENT_SYNC_HIST">
            <column name="ID" remarks="主键" type="VARCHAR(38)">
                <constraints nullable="false" primaryKey="true"/>
            </column>
            <column name="CREATE_TIME" remarks="创建时间" type="datetime"/>
            <column name="UPDATE_TIME" remarks="更新时间" type="datetime"/>
            <column name="APP_NAME" remarks="应用名称事件操作者" type="VARCHAR(255)"/>
            <column name="LAST_SYNC_TIME" remarks="上一次同步时间" type="datetime"/>
            <column name="TENANT_ID" remarks="租户id" type="VARCHAR(38)">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>
    <changeSet id="1697708034037-16" author="shidaobang" runOnChange="true">
        <preConditions onFail="MARK_RAN">
            <not>
                <indexExists tableName="Y9_COMMON_ACCOUNT" columnNames="LOGIN_NAME"/>
            </not>
        </preConditions>
        <createIndex indexName="IDX7d3kas0oqvn2o3sv6m7wjecr2" tableName="Y9_COMMON_ACCOUNT">
            <column name="LOGIN_NAME"/>
        </createIndex>
    </changeSet>

</databaseChangeLog>

更多初始化和更新等操作可参考:liquibase官网

项目启动

项目启动并完成数据源的初始化后,liquibase 会对公共库及租户库执行数据库表的所有变更。 如果是再次启动项目,由于 liquibase 表中已记录执行过的 changeset,变更不会再次执行。

Released under the GPL-3.0 License.