Liquibase使用教程

2022-07-01 11:00 阅读

Liquibase是开源的数据库表结构管理解决方案,可以轻管理表结构的变更。

众所周知,使用git管理代码可以使得多人协作、版本管理等工作变得异常轻松。但数据库表结构的管理却一直没有很好的解决方案,比如每次变更数据库都要手动执行SQL脚本,不同版本的程序和不同版本的数据库表结构要小心的匹配,跨数据库平台的还需为不同数据库准备不同SQL脚本,数据库表结构只能升级、不能降级。

参考资料

支持的数据库

Liquibase支持大部分数据库(如果不是所有的话),包括:mysql, postgresql, mariadb, mssql, oracle, db2, sybase, h2, derby, firebird, hsqldb, sqlite。

参考资料

工作原理

Liquibase使用一种通用的语言描述数据库的变更,代替传统的SQL语句,以实现上述目标。

Liquibase允许使用SQL、XML、JSON、YAML文件格式。SpringBoot默认使用YAML文件格式,这里以YAML格式为例进行说明。

如要为person表增加country列,通常SQL代码为:ALTER TABLE person ADD country varchar(2),在Liquibase中则描述为:

- changeSet:
       id:  4
       author:  your.name
       changes:
        - addColumn:
             tableName:  person
             columns:
               - column:
                   name:  country
                   type:  varchar(2)

其中id是该changeSet的唯一标识,author则标记该changeSet是谁编写的。

Liquibase可以根据此描述,为不同数据库生成不同SQL代码。并且会在数据库中自动创建DATABASECHANGELOG表,用于记录哪些changeSet是执行过的。

由此可知Liquibase的原理还是很简单的。

参考资料

Liquibase语句

只要是SQL支持的Liquibase绝大部分都支持。如createTable, addColumn, dropTable, dropColumn, renameColumn, modifyDataType, createIndex, addForeignKeyConstraint 等等。

以下是createTable(创建表)的语句:

changeSet:
  id:  createTable-example
  author:  liquibase-docs
  changes:
  -  createTable:
      columns:
      -  column:
          name:  address
          type:  varchar(255)
      tableName:  person

详细语句请参考官方文档:Liquibase Change Types

在SpringBoot中的使用

SpringBoot自带了对Liquibase的支持,使用起来非常方便。只需要在pom.xml中增加如下配置:

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

默认的yaml文件位于src/main/resources/ db/changelog/db.changelog-master.yaml,可以直接在这个文件上写入Liquibase代码。

但最佳实践是将不同版本的changelog放在独立的文件。例如1.0版本的changelog为db.changelog-1.0.yaml2.0版本的chagelog为db.changelog-2.0.yaml。在db.changelog-master.yaml将其包含进来。

databaseChangeLog:
  - include:
      file: db.changelog-1.0.yaml
      relativeToChangelogFile: true
  - include:
      file: db.changelog-2.0.yaml
      relativeToChangelogFile: true

完成SpringBoot的配置之后,程序启动时就会解析db.changelog-master.yaml文件的内容,并和Liquibase自动创建的DATABASECHANGELOG表的内容进行比对,没有执行的changelog会根据当前数据库类型生成相应的SQL自动执行,并写入DATABASECHANGELOG

需要注意的是,Liquibase并不会对表结构自动回滚。比如git从2.0版本切换到1.0版本,数据库结构不会自动回滚到1.0版本。因为数据库结构回滚可能会删表(表里的数据也就没了),是风险极大的操作。Liquebase支持数据库结构回滚,给不同版本的数据库结构做tag标记,可回滚到某个标记处。对于某些Liquibase无法自动生成回滚语句的(比如insert、update语句),需要自己在changelog编写回滚语句。这些是高级用法,且用的极少,这里就不多做介绍。

在UJCMS项目中就使用了Liquibase作为数据库版本管理工具,可参考实例代码:UJCMS db.changelog-master.yaml

参考资料

字段默认值

Liquibase对字段默认值的处理非常值得注意,使用defaultValue的内容一律作为字符串处理,如果希望使用其它数据类型,应使用相应的属性。

  • defaultValue:字符串
  • defaultValueBoolean:布尔值
  • defaultValueNumeric:数值
  • defaultValueDate:日期。使用其中一种格式:YYYY-MM-DD,hh:mm:ssorYYYY-MM-DDThh:mm:ss
  • defaultValueComputed:表达式。特别的,使用current_timestamp current_datetime 或者 current_timestamp(3)可自动转化为相应数据库的日期函数,如MySQL的now() now(3)

参考资料:

property的使用

proerty可以支持数据库类型判断,如:

<property name="now" value="sysdate" dbms="oracle"/>
<property name="now" value="now()" dbms="mysql"/>
<property name="now" value="now()" dbms="postgresql"/>

<column name="join_date" defaultValueComputed="${now}"/>

其它问题

  • 无法对MySQL单独增加字段注释,增加注释时,可能会丢失字段非空约束。修改字段类型、增加非空约束时,会丢失字段注释。所以不要纠结MySQL字段的注释问题。
  • 不要使用drop primary key,达梦不支持。应该先改表名、新建无约束新表(包括不要主键)、复制数据、删旧表、新表加约束。
咨询
交流群
电话