boot-admin整合Liquibase实现数据库版本管理

Liquibase 和 Flyway 是两款成熟的、优秀的、开源/商业版的数据库版本管理工具,鉴于 Flyway 的社区版本对 Oracle 数据库支持存在限制,所以 boot-admin 选择整合 Liquibase 提供数据库版本管理能力支持。
Liquibase 开源版使用 Apache 2.0 协议。

Liquibase的适用情形?

  • 在你的项目进行版本升级的时候,大概率情况下数据库也需要同步升级,Liquibase 会自动扫描数据库迁移文件(changeSet),将迁移文件的版本号与历史记录表(changelog )中的版本号进行对比,略过已执行的的迁移文件,顺序执行未执行的新版本迁移文件,最终实现数据库与代码版本相匹配;
  • 当多人协作开发项目的时候,系统源代码可使用 git 保持同步,那么数据库的同步就可交由 liquibase 来保证;
  • 使用 liquibase 可以方便地比较两个数据库的差异;
  • 使用 liquibase 还支持数据库版本回滚。

Liquibase的优点有哪些?

  1. 配置文件支持SQL、XML、JSON 或者 YAML;
  2. 可兼容14种主流数据库如 oracle,mysql 等,支持平滑迁移;
  3. 版本控制按序执行;
  4. 可以用上下文控制sql在何时何地如何执行;
  5. 具备在应用中具有if / then逻辑的能力;
  6. 支持 schema 的变更;
  7. 根据配置文件自动生成sql语句用于预览;
  8. 可重复执行迁移;
  9. 可插件拓展;
  10. 可回滚;
  11. 支持schema方式的多租户(multi-tenant);
  12. 能够在多种数据库类型上具有相同的更改描述;
  13. 生成的数据库历史记录文档;
  14. 能够轻松指定更复杂的多语句更改。

整合要点

boot-admin 是一款采用前后端分离模式、基于 SpringCloud 微服务架构的SaaS后台管理框架。系统内置基础管理、权限管理、运行管理、定义管理、代码生成器和办公管理6个功能模块,集成分布式事务 Seata、工作流引擎 Flowable、业务规则引擎 Drools、后台作业调度框架 Quartz 等,技术栈包括 Mybatis-plus、Redis、Nacos、Seata、Flowable、Drools、Quartz、SpringCloud、Springboot Admin Gateway、Liquibase、jwt、Openfeign、I18n等。

项目源码仓库github
项目源码仓库gitee

引入Maven依赖

<dependency>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-core</artifactId>
</dependency>

添加配置

spring:
  liquibase:
    enabled: true
    change-log: classpath:liquibase/master.xml

创建master.xml

在 resources 下创建文件夹 liquibase ,创建文件 master.xml

<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-3.1.xsd">

    <includeAll path="liquibase/changelogs/" relativeToChangelogFile="false"/>

</databaseChangeLog>

在 liquibase 文件夹下创建 changelogs 和 sql 两个文件夹,如下图所示:

编写数据库变更单元 changeSet

在 resources\liquibase\changelogs 下创建 changeSet 文件,推荐每月一个 xml 文件,文件名格式:【changelog-年度+月份.xml】,如:changelog-202304.xml
常用操作举例:

创建表

    <changeSet author="admin (generated)" id="00001-9">
        <createTable remarks="行政区划表" tableName="TB_ADM_DIV">
            <column name="GUID" remarks="主键" type="NVARCHAR2(38)">
                <constraints nullable="false" primaryKey="true" primaryKeyName="PK_TB_ADM_DIV"/>
            </column>
            <column name="ADM_DIV_CODE" remarks="行政区划代码" type="NVARCHAR2(12)">
                <constraints nullable="false"/>
            </column>
            <column name="ADM_DIV_NAME" remarks="行政区划名称" type="NVARCHAR2(100)">
                <constraints nullable="false"/>
            </column>
            <column name="CREATE_BY" remarks="记录创建者" type="NVARCHAR2(100)">
                <constraints nullable="false"/>
            </column>
            <column name="CREATE_TIME" remarks="记录创建时间" type="${type.datetime}">
                <constraints nullable="false"/>
            </column>
            <column name="MODIFY_BY" remarks="记录最后修改者" type="NVARCHAR2(100)">
                <constraints nullable="false"/>
            </column>
            <column name="MODIFY_TIME" remarks="记录最后修改时间" type="${type.datetime}">
                <constraints nullable="false"/>
            </column>
            <column defaultValueComputed="${now}" name="DATESTAMP" remarks="时间戳" type="${type.datetime}">
                <constraints nullable="false"/>
            </column>
            <column name="ENABLED" remarks="启用状态;ENABLED" type="NVARCHAR2(1)">
                <constraints nullable="false"/>
            </column>
            <column name="DELETED" remarks="删除状态;DELETED" type="NVARCHAR2(1)">
                <constraints nullable="false"/>
            </column>
            <column name="VERSION" remarks="乐观锁" type="${type.int}">
                <constraints nullable="false"/>
            </column>
            <column name="REMARKS" remarks="备注" type="NVARCHAR2(900)"/>
            <column name="TENANT_ID_" remarks="租户ID" type="NVARCHAR2(38)">
                <constraints nullable="false"/>
            </column>
            <column name="PARENT_GUID" remarks="父级GUID" type="NVARCHAR2(38)">
                <constraints nullable="false"/>
            </column>
            <column name="LEAF" remarks="是否末级;YESNO" type="NVARCHAR2(1)">
                <constraints nullable="false"/>
            </column>
            <column name="SORT" remarks="顺序号" type="${type.int}">
                <constraints nullable="false"/>
            </column>
        </createTable>
    </changeSet>

添加表字段

<changeSet author="admin" id="00002-1">
    <addColumn tableName="TB_ADM_DIV">
       <column name="EXT" remarks="扩展" type="VARCHAR(64)"/>
    </addColumn>
</changeSet>

删除表字段

    <changeSet author="admin" id="00002-2">
        <dropColumn tableName="TB_ADM_DIV" columnName="EXT"/>
    </changeSet>

修改表字段说明

    <changeSet author="admin" id="00002-3">
        <setColumnRemarks tableName="TB_ADM_DIV" columnName="EXT" remarks="扩展字段"/>
    </changeSet>

修改表字段类型

    <changeSet author="admin" id="00002-4">
        <modifyDataType tableName="TB_ADM_DIV" columnName="EXT" newDataType="VARCHAR2(2000)"/>
    </changeSet>

创建视图

    <changeSet author="admin (generated)" id="00001-1" dbms="oracle">
        <createView fullDefinition="true" remarks="表和视图" viewName="V_TABLES_MASTER">
            CREATE OR REPLACE FORCE VIEW V_TABLES_MASTER (TABLE_SCHEMA, TABLENAME, TABLETYPE, COMMENTS, TENANT_ID_) AS
            select SYS_CONTEXT('USERENV','CURRENT_SCHEMA') TABLE_SCHEMA,
            t.tname tableName,
            tabtype tabletype,
            f.comments comments,
            'DEMO' TENANT_ID_
            from tab t
            inner join user_tab_comments f
            on t.tname = f.table_name
            where tname != 'DATABASECHANGELOG'
            and tname != 'DATABASECHANGELOGLOCK'
            and tname != 'UNDO_LOG'
        </createView>
    </changeSet>
    <changeSet author="37514 (generated)" id="00000-2" dbms="mysql">
        <createView fullDefinition="true" remarks="表和视图" viewName="V_TABLES_MASTER">
            CREATE OR REPLACE VIEW V_TABLES_MASTER  AS
            SELECT
            TABLE_SCHEMA,
            TABLE_NAME AS TABLENAME,
            case when table_type='BASE TABLE' then 'TABLE' ELSE table_type END AS TABLETYPE,
            TABLE_COMMENT AS COMMENTS,
            'DEMO' TENANT_ID_
            FROM
            information_schema.`TABLES`
            WHERE table_name != 'databasechangeloglock' AND TABLE_NAME != 'databasechangelog' AND TABLE_NAME != 'undo_log'
        </createView>
    </changeSet>

兼容 Oracle 和 Mysql 配置

    <property name="type.datetime" value="date" dbms="oracle"/>
    <property name="type.datetime" value="timestamp" dbms="mysql"/>
    <property name="type.int" value="NUMBER(*, 0)" dbms="oracle"/>
    <property name="type.int" value="INT" dbms="mysql"/>
    <property name="type.decimal" value="NUMBER(*, 2)" dbms="oracle"/>
    <property name="type.decimal" value="DECIMAL" dbms="mysql"/>
    <property name="now" value="SYSDATE" dbms="oracle"/>
    <property name="now" value="now()" dbms="mysql,h2"/>
    <property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle"/>
    <property name="amount" value="decimal(20,2)"/>
    <property name="uuid" value="sys_guid()" dbms="oracle"/>
    <property name="uuid" value="UUID()" dbms="mysql"/>

执行 SQL 文件

    <changeSet id="20000820-003" author="Administrator" dbms="oracle">
        <sqlFile dbms="oracle" path="classpath:/liquibase/sql/seata-undo_log-oracle.sql" />
    </changeSet>
    <changeSet id="20000820-003" author="Administrator" dbms="mysql">
        <sqlFile dbms="mysql" path="classpath:/liquibase/sql/seata-undo_log-mysql.sql" />
    </changeSet>

需将对应 sql 文件放在指定文件夹中。

Liquibase changeSet常用命令清单

add

标签 描述
addAutoIncrement 将一个已存在的列转换为自增
addColunm 增加列
addDefaultValue 对已存在的列增加默认值
addForeignKeyConstraint 对已存在的列增加外键约束
addLookupTable 创建外键关联的表
addNotNullConstraint 对已存在的列增加非空约束
addPrimaryKey 对已存在的列增加主键约束
ddUniqueConstraint 对已存在的列增加主键约束

create

标签 描述
createIndex 创建索引
createProcedure 创建存储过程
createSequence 创建序列
createTable 创建表
createView 创建视图

drop

标签 描述
dropAllForeignKeyConstraints 删除全部的外键约束
dropColumn 删除列
dropDefaultValue 删除默认值设置
dropForeignKeyConstraint 删除某一列的外键约束
dropNotNullConstraint 删除非空约束
dropIndex 删除索引
dropSequence 删除约束
dropProcedure 删除存储过程
dropPrimaryKey 删除主键
dropTable 删除表
dropUniqueConstraint 删除唯一性约束
dropView 删除视图

rename

标签 描述
renameColumn 重命名列
renameSequence 重命名序列
renameTable 重命名表
renameView 重命名视图

sql

标签 描述
sql 原生SQL
sqlFile 引入 SQL 文件

othr

标签 描述 标签 描述
alterSequence 修改序列 customChange 自定义change类型,需要自己实现liquibase.change.custom.CustomSqlChange、liquibase.change.custom.CustomTaskChange接口
delete 删除数据 empty 空操作
executeCommand 执行系统命令,如 mysqldump insert 插入数据
loadData 加载 csv 文件到已存在的表中 loadUpdateData 加载 csv 文件到已存在的表中,但是会判断是否存在,存在更新,否则新增
mergeColumns 将两列值合并在一起,存入新列中 modifyDataType 修改列数据类型
output 记录一条消息并继续执行 setColumnRemarks 列上添加备注
setTableRemarks 表上添加备注 stop 通过消息停止 Liquibase
tagDatabase 将标签应用于数据库以供将来回滚 update 更新数据

原文链接:https://www.cnblogs.com/soft1314/p/17375273.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:boot-admin整合Liquibase实现数据库版本管理 - Python技术站

(0)
上一篇 2023年5月5日
下一篇 2023年5月6日

相关文章

  • Java调用C++程序的实现方式

    Java调用C++程序的实现方式主要涉及两个方面:JNI和JNA。接下来,我将分别介绍这两种实现方式。 使用JNI实现Java调用C++程序 JNI是Java Native Interface的简称,是Java提供的一种本地方法调用的标准接口。它允许Java程序和本地代码(例如C++、C等)进行交互,并提供了一系列的API接口用于支持Java程序与本地代码的…

    Java 2023年5月19日
    00
  • jsp中select的onchange事件用法实例

    以下是“jsp中select的onchange事件用法实例”完整攻略: 1. 什么是select的onchange事件 select标签是HTML中常用的选项框,而onchange事件则是当下拉选项列表的值发生改变时触发的事件。onchange事件通常与JavaScript函数一起使用,来实现对选项框的动态控制。 2. select的onchange事件用法…

    Java 2023年6月15日
    00
  • Java 安全模型,你了解了吗

    Java 安全模型,你了解了吗? Java是一种广泛用于应用程序和互联网的编程语言,其安全模型可确保Java代码执行时的安全性和完整性,从而使Java成为一种极具安全性的编程语言。下面来介绍Java安全模型的完整攻略。 Java安全模型基础 Java安全模型是由Java运行环境提供的一种安全机制,它通过控制Java程序访问资源的方式来保护主机和网络中的资源。…

    Java 2023年5月24日
    00
  • 详解Jvm中时区设置方式

    我来详细讲解一下“详解Jvm中时区设置方式”的完整攻略。 什么是Jvm中的时区 Jvm是一种Java虚拟机,它是运行Java程序的基础。在Java程序中,时间是一个非常重要的概念,因此时区是一个必不可少的因素。Jvm中的时区设置可以控制Java程序使用的时间和日期格式。 Jvm中的时区设置方式 Jvm中的时区设置有三种方式,分别为: 1. 系统默认时区 Jv…

    Java 2023年5月20日
    00
  • java根据开始时间结束时间计算中间间隔日期的实例代码

    以下是Java根据开始时间结束时间计算中间时间间隔的实例代码完整攻略。 标题 Java根据开始时间结束时间计算中间时间间隔的实例代码 描述 在Java中,我们经常需要在两个日期之间计算天数、小时数或分钟数。此时需要使用Java提供的时间类库。Java日期类库中的Date和Calendar类提供了很多用于处理日期和时间的方法。下面我们将演示如何使用Java代码…

    Java 2023年6月1日
    00
  • 基于javax.validation结合spring的最佳实践

    基于javax.validation结合Spring的最佳实践,主要是利用Spring框架提供的Validator和DataBinder接口以及javax.validation提供的注解和API对请求参数和数据模型进行合法性校验,来保证应用程序的数据输入和输出的正确性。 下面是基于Spring Boot的完整攻略: 1. 引入依赖 在pom.xml文件中引入…

    Java 2023年5月19日
    00
  • 基于SpringBoot bootstrap.yml配置未生效的解决

    在Spring Boot应用程序中,我们可以使用bootstrap.yml或bootstrap.properties文件来配置应用程序的属性。但是,有时候我们可能会遇到配置未生效的问题。下面是详解基于Spring Boot bootstrap.yml配置未生效的解决方案的完整攻略: 确认配置文件位置 首先,我们需要确认bootstrap.yml文件的位置是否…

    Java 2023年5月14日
    00
  • Mybatis自关联查询一对多查询的实现示例

    下面是详细讲解“Mybatis自关联查询一对多查询的实现示例”的完整攻略。 什么是自关联查询 自关联查询是指在一个表中通过外键的方式连接同一张表的两行或多行数据的查询方式。比如,在员工表中,如果需要查询员工和他们的直接上级,可以通过员工表中的经理编号字段来连接同一员工表。 自关联查询的实现 自关联查询在Mybatis框架下的实现方式有两种: 使用Mybati…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部