Liquibase实践指南

本文详细介绍了Liquibase的使用,包括其作为数据库版本控制工具的功能,如何在SpringBoot项目中集成,以及如何通过命令行和配置文件进行数据库变更管理。内容涵盖Liquibase的特点、实践操作、与SpringBoot的集成、配置属性详解,以及变更集的操作,如创建表、插入数据、回滚等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Liquibase实践指南

1、概述

本文主要介绍了 什么是 Liquibase,以及在 SpringBoot 项目中集成使用 Liquibase 对数据库表进行管理,包括自动创建数据库表、自动初始化数据、更新表结构。

2、认识 Liquibase

官网:Liquibase | Database Refactoring | Liquibase: http://www.liquibase.org/
Liquibase 是用于数据库重构、管理、记录变化与回滚的开源工具。
在写代码的时候,我们使用 Git 或 subversion 对代码进行版本控制,在数据库中,我们可以使用 liquibase 对数据库表进行版本控制。

3、Liquibase 特点

  • 支持项目代码多人多分支开发与合并;
  • 支持多种数据库类型:MySQL、PostgreSQL、Oracle、Sql Server、DB2、H2等,更多信息请移步官网: http://www.liquibase.org/databases.html ;
  • 支持多种变化日志格式:XML、YML、JSON、SQL;
  • 支持自定义上下文执行逻辑,可指定需要运行的上下文;
  • 集群安全的数据库更新;
  • 可生成数据库修改文档(HTML);
  • 使用命令对比两个数据库;
  • 可以使用 build 工具(Command Line、Ant、Maven)运行,也可以嵌入到 Application 中;
  • 可以自动生成数据库 SQL 脚本,供 DBA 重构代码使用;
  • 可以使用离线数据库;

4、Liquibase实践

4.1、环境依赖

  • windows 操作系统 PC/Mac OS
  • Java 1.8 运行环境,liquibase 2.x 依赖 java 1.5+,3.x 依赖 java1.6+
  • Maven 3.0
  • MySQL 5.7
  • liquibase 3.6.3
  • (可选)Navicat for MySQL ,用于查看数据库表结构与数据

4.2、使用命令行体验 Liquibase

下载压缩包

官网下载地址:https://download.liquibase.org/download/?frm=n
liquibase-3.6.3-bin.zip: 我的下载地址

download liquibase

解压文件、下载 JDBC jar 包

将上一步下载好的 liquibase zip 包解压出来。
我电脑上使用的 MySQL ,所以我需要下载 mysql-connector-java 用来连接操作数据库,我这里使用的版本是 8.0.13,下载下来后将这个 jar 包放到 liquibase 根目录下的 lib 文件夹中,使用 liquibase 时,会自动扫描 lib 下的包。

下载地址:mysql-connector-java-8.0.13

创建数据库修改日志文件(database chanagelog file)

liquibase 支持多种格式的日志文件,包括 XML、YML、JSON、SQL,官方推荐使用 xml,个人喜欢更加简洁的 yml 格式。在 liquibase 根目录下创建文件夹 chanagelog ,用来存储修改日志文件。从官网拷贝示例,存储到 chanagelog 目录下,文件名为 master.yml ,文件内容如下:

注意直接从官方文档中考出来的,要修改 databaseChangeLog.preConditions.runningAs.username ,改为自己数据库的用户名,我使用的是 root 。

databaseChangeLog:
  - preConditions:
    - runningAs:
        username: root

  - changeSet:
      id: 1
      author: nvoxland
      changes:
        - createTable:
            tableName: person
            columns:
              - column:
                  name: id
                  type: int
                  autoIncrement: true
                  constraints:
                    primaryKey: true
                    nullable: false
              - column:
                  name: firstname
                  type: varchar(50)
              - column:
                  name: lastname
                  type: varchar(50)
                  constraints:
                    nullable: false
              - column:
                  name: state
                  type: char(2)

  - changeSet:
      id: 2
      author: nvoxland
      changes:
        - addColumn:
            tableName: person
            columns:
              - column:
                  name: username
                  type: varchar(8)

  - changeSet:
      id: 3
      author: nvoxland
      changes:
        - addLookupTable:
            existingTableName: person
            existingColumnName: state
            newTableName: state
            newColumnName: id
            newColumnDataType: char(2)
运行命令

在数据库中新建数据库 test_liquibase,在 liquibase 根目录打开命令行,执行命令

liquibase.bat --url="jdbc:mysql://localhost:3306/test_liquibase?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8" --changeLogFile="/chanagelog/master.yml" --username=root --password=123456 --driver=com.mysql.cj.jdbc.Driver update

liquibase 命令中必须的必须选项有:
–url=数据库连接,其中 serverTimezone=GMT%2B8 参数用来指定时区,在使用高版本 jdbc 时需要,不指定可能会报时区错误
–chanagelog=数据库修改日志文件
–username=数据库用户名
–password=数据库密码
–driver=数据库连接驱动
最后的 update 是 liquibase 命令,必须放到选项的后面。
关于命令的更多内容可以使用 liquibase --help 命令查看帮助信息,也可以到官网查询详细信息: http://www.liquibase.org/documentation/command_line.html

执行结果:
update success

检查数据库

查看 test_liquibase 数据库,发现多了 4 张表:
数据库表

打开 databasechanagelog 表,发现在 master.yml 中的 3 个修改都已经被执行了(表中 EXECTYPE 值为 EXECUTED)。
databasechanagelog

4.3、SpringBoot 项目集成 Liquibase

SpringBoot 提供了自动装配,大大降低了其它组件的使用难度,在使用 Liquibase 时,可以说非常简单了。

4.3.1、创建项目

创建一个 SpringBoot 项目,添加依赖 web、jpa、liquibase,最终项目 pom.xml 如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.3.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>xyz.wqf</groupId>
	<artifactId>liquibasedemo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>liquibasedemo</name>
	<description>Demo project for Spring Boot with Liquibase</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<!--jpa-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		
		<!--web-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<!--liquibase-->
		<dependency>
			<groupId>org.liquibase</groupId>
			<artifactId>liquibase-core</artifactId>
		</dependency>
    <!--liquibase-->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>
4.3.2、添加 changelog 与数据

为了放管理,我们在项目 resources 目录下创建 liquibase 目录用于存放 liquibase 相关的配置文件,在 liquibase 目录下创建 changelog 目录存放所有 changelog 文件,创建 initdata 目录用于存放初始化项目时的数据。
项目 Resource 目录

4.3.2.1、changelog

liquibase 目录下的 master.xml 为 liquibase 的入口,通过 include 标签将其它的 changelog 文件引入进来。

  • master.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"
          xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
          xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
          http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
    
      <include file="classpath:liquibase/changelog/init_00000000000000.xml" relativeToChangelogFile="false"/>
      <include file="classpath:liquibase/changelog/user_20190313171720.xml" relativeToChangelogFile="false"/>
    	
    </databaseChangeLog>
    
  • init_00000000000000.xml

    <databaseChangeLog
            xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
            xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
            http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
    
        <property name="now" value="now()" dbms="mysql,h2"/>
        <property name="now" value="current_timestamp" dbms="postgresql"/>
        <property name="now" value="sysdate" dbms="oracle"/>
    
        <property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle"/>
    
        <property name="floatType" value="float4" dbms="postgresql, h2"/>
        <property name="floatType" value="float" dbms="mysql, oracle"/>
    
        <changeSet id="20190313172000" author="wqf31415">
            <createTable tableName="book">
                <column name="id" type="bigint" autoIncrement="${autoIncrement}">
                    <constraints nullable="false" primaryKey="true"/>
                </column>
    
                <column name="title" type="varchar(255)" remarks="书名">
                    <constraints nullable="false"/>
                </column>
    
                <column name="description" type="text" remarks="描述">
                    <constraints nullable="true"/>
                </column>
    
                <column name="price" type="${floatType}" remarks="价格">
                    <constraints nullable="true"/>
                </column>
    
                <column name="add_time" type="timestamp" defaultValue="${now}">
                    <constraints nullable="true"/>
                </column>
            </createTable>
        </changeSet>
    </databaseChangeLog>
    
  • user_20190313171720.xml

    <databaseChangeLog
          xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
          xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
          http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
    
      <property name="now" value="now()" dbms="mysql,h2"/>
      <property name="now" value="current_timestamp" dbms="postgresql"/>
      <property name="now" value="sysdate" dbms="oracle"/>
    
      <property name="autoIncrement" value="true" dbms="mysql,h2,postgresql,oracle"/>
    
      <property name="floatType" value="float4" dbms="postgresql, h2"/>
      <property name="floatType" value="float" dbms="mysql, oracle"/>
    
      <changeSet id="20190313172800" author="wqf31415">
          <createTable tableName="user">
              <column name="id" autoIncrement="${autoIncrement}" type="bigint">
                  <constraints nullable="false" primaryKey="true" />
              </column>
    
              <column name="name" type="varchar(255)" remarks="姓名">
                  <constraints nullable="true"/>
              </column>
    
              <column name="password" type="varchar(255)" remarks="密码">
                  <constraints nullable="true"/>
              </column>
    
              <column name="age" type="tinyint" remarks="年龄">
                  <constraints nullable="true"/>
              </column>
    
              <column name="birthday" type="date" remarks="生日">
                  <constraints nullable="true"/>
              </column>
          </createTable>
    
    	<!--导入数据-->
          <loadData tableName="user" file="classpath:liquibase/initdata/user.csv" separator=";" encoding="UTF-8"/>
      </changeSet>
    </databaseChangeLog>
    
4.3.2.2、数据

在项目初始化,liquibase 完成建表后,可以导入预先定义好的数据。

  • user.csv
id;name;password;age;birthday
1;zhangsan;abc123;18;2001-03-23
2;lisi;ls1990;27;1990-11-08
4.3.3、修改配置文件

修改项目配置文件,添加数据库相关的配置,指定 liquibase 的 changelog文件。

server:
  port: 8909
spring:
  datasource:
    url: jdbc:mysql://172.16.19.229:3306/liquibase_demo?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  jpa:
    show-sql: true
  application:
    name: LiquibaseDemo
  liquibase:
    change-log: classpath:liquibase/master.xml # 指定 changelog 文件
4.3.4、运行项目

在运行项目前需要提前创建 url 中指定的数据库,我这里需要创建名为 liquibase_demo 的数据库。
运行项目,查看数据库,建表正确且 user 表中数据正确。
初始化的数据

5、SpringBoot 配置文件-属性详解

5.1、SpringBoot 配置项

下表是在 SpringBoot 2.1.3.RELEASE 使用 liquibase 的配置项
在 SpringBoot 1.x 版本中 liquibase 配置项少一些,且配置项没有 spring,如 2.x 中的 spring.liquibase.change-log ,在 1.x 中为 liquibase.change-log

配置项默认值注释
spring.liquibase.change-logclasspath:/db/changelog/db.changelog-master.yamlchangeLogFile 配置路径
spring.liquibase.check-change-log-locationtrue是否检查 changelog 配置路径存在
spring.liquibase.contexts只有指定的 context 的 changelog 才会被执行,多个 context 之间以逗号分隔
spring.liquibase.default-schema默认数据库
spring.liquibase.liquibase-schema用于存储 liquibase 对象的数据库
spring.liquibase.liquibase-tablespace用于 liquibase 对象的表空间
spring.liquibase.database-change-log-tableDATABASECHANGELOG存储数据库改变记录执行情况的表名
spring.liquibase.database-change-log-lock-tableDATABASECHANGELOGLOCK存储当前使用 liquibase 的用户信息表名
spring.liquibase.drop-firstfalse是否先删除表
spring.liquibase.enabledtrue是否启用 liquibase
spring.liquibase.userliquibase 使用的数据库用户名,不指定时使用 spring.datasource 中的
spring.liquibase.passwordliquibase 使用的数据库用户密码,不指定时使用 spring.datasource 中的
spring.liquibase.urlliquibase 使用的数据库url,不指定时使用 spring.datasource 中的
spring.liquibase.labels指定标签的才会运行,多个标签以逗号分隔
spring.liquibase.parameterschangelog 参数
spring.liquibase.rollback-file当执行升级时写回滚 SQL 的文件
spring.liquibase.test-rollback-on-update执行更新前是否验证回滚

6、Liquibase changelog 标签

6.1、ChangeLog 文件

所有 Liquibase 更改的根目录是databaseChangeLog文件。

6.1.1、ChangeLog可用属性

logicalFilePath:用于在创建changeSet的唯一标识符时覆盖文件名和路径。移动或重命名change logs时是必需的。

<?xml version="1.0" encoding="utf-8" ?>
<databaseChangeLog logicalFilePath="" 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">

</databaseChangeLog>
6.1.2、ChangeLog 可用子标签
6.1.2.1、preConditions 前提条件

可以附加preConditionsdatabaseChangeLogchangeSet,以控制基于数据库状态的更新的执行。

下面是使用preConditions的几个原因:

  • 记录changelog的作者在创建changelog时的假设。

  • 强制运行changelog的用户不违反这些假设。

  • 在执行不可恢复的更改(例如dropTable)之前,请执行数据检查。

  • 根据数据库的状态来控制运行哪些changesets和不运行哪些changesets

可用的属性
  • onFail: 当proConditions遇到失败的时候如何处理
  • onError:当proConditions遇到错误的时候如何处理
  • onUpdateSQL:自版本1.9.5后当proConditions遇到更新SQL模型的时候如何处理
  • onFailMessage:自2.0起,在proConditions失败时要输出的自定义消息。
  • onErrorMessage:在proConditions错误时要输出的自定义消息。
onFail或者onError可能的取值
  • HALT:立即停止执行整个changelog。默认的值。
  • CONTINUE:跳过changeset。将在下次更新时再次尝试执行changeset。继续changelog
  • MARK_RAN:跳过changeset,但将其标记为已执行。继续changelog
  • WARN:输出警告并继续正常执行changeset/changelog

changset之外(例如,在changelog的开头),只有 HALTWARN 两种数值。

AND/OR/NOT逻辑

可以使用可嵌套<and><or><not>标签将条件逻辑应用于preConditions。如果未指定条件标签,则默认为 <AND>

可用的preConditions

<dbms>:

  • 如果针对所执行的数据库与指定的类型匹配,则通过。
  • type:预期的数据库类型。可以使用逗号分隔值指定多个 dbms 值。必填

<runningAs>:

  • 如果执行的数据库用户与指定的用户名匹配,则通过。
  • username:数据库用户脚本应以原样运行。必填

<columnExists>:

  • 从1.8开始如果数据库中存在具体的列,则通过
  • schemaName:表的schema的名称。必填
  • tableName:列表的名称。必填
  • columnName:列名称。必填

<tableExists>:

  • 从1.8开始,如果数据库中存在具体的表,则通过
  • schemaName:表的schema的名称。必填
  • tableName:表的名称。必填

<viewExists>:

  • 从1.8开始,如果数据库中存在具体的视图,则通过
  • schemaName:视图的schema的名称。必填
  • viewName:视图的名称。必填

<foreignKeyConstrainExists>:

  • 从1.8开始,如果数据库存在指定的外键,则通过
  • schemaName:外键的schema名称,必填
  • foreignKeyName:外键的名称。必填

<indexExists>:

  • 从1.8开始,如果数据库存在指定的索引,则通过
  • schemaName:索引的schema名称,必填
  • indexName:索引名称,必填

<sequenceExists>:

  • 从1.8开始,如果数据库存在指定的序列,则通过
  • schemaName:序列的schema名称,必填
  • sequenceName:序列的名称,必填

<primaryKeyExists>:

  • 从1.8开始,如果数据库中存在指定的主键,则通过
  • schemaName:主键的schema名称
  • primaryKeyName:主键的名称,表名或者主键名是必填
  • tableName:包含主键的表的名称。从1.9开始表名或者主键名是必填

<sqlCheck>:

  • 执行 SQL 字符串并检查返回的值。SQL 必须返回具有单个值的单个行。要检查行数,请使用SQL 函数count。要检查值范围,请在 SQL 中执行检查,并返回一个可以容易比较的值。
<sqlCheck expectedResult="1">
    SELECT COUNT(1) FROM pg_tables WHERE TABLENAME = 'myRequiredTable'
</sqlCheck>
  • expectedResult:这个值与SQL的执行结果作比较,必填

<changeLogPropertyDefined>:

  • 检查是否存在给定的changelog参数。如果还给定了值,则仅当该值与给定值不同时,该值才会失败。
  • property:要检验的属性的名称,必填
  • value:给定属性的必需值。

<customPrecondition>:

  • 可以通过创建实现 liquibase.precondition.CustomPrecondition接口的类来创建自定义precondition。自定义类上的参数通过基于<param>子标签的反射进行设置。参数作为字符串传递到自定义preCondition

    <customPrecondition className="com.example.CustomTableCheck">
        <param name="tableName" value="our_table"/>
        <param name="count" value="42"/>
    </customPrecondition>
    
  • className:custom precondition类的名称。必填

  • 子标签

    • param:传递给custom precondition的参数
      • param子标签属性:
        • name:要设置的参数的名称。必填
        • value:要将参数设置为的字符串值。必填

具体属性及使用方法请查看 官方文档

6.1.2.2、property

从Liquibase 1.7开始

Liquibase 允许在changelog中动态替换参数。使用 ${} 语法描述要替换的参数。

配置参数的值

参数的值会被按照下面的顺序进行查找

  • 作为参数传递给您的 Liquibase 运行程序(请参阅 Antcommand等文档,了解如何传递它们)ant和command没有了解
  • 作为 JVM系统属性
  • 在数据库ChangeLog文件本身的参数块(<property>标签)中
  • 作为环境变量
<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog 	http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd
        http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">

    <property name="clob.type" value="clob" dbms="oracle"/>
    <property name="clob.type" value="longtext" dbms="mysql"/>

    <changeSet id="1" author="joe">
         <createTable tableName="${table.name}">
             <column name="id" type="int"/>
             <column name="${column1.name}" type="${clob.type}"/>
             <column name="${column2.name}" type="int"/>
         </createTable>
    </changeSet>
</databaseChangeLog>

可用属性

  • name:表schema的名称;必填
  • value:列表的名称;必填
  • context:以逗号分隔列表表示的上下文。
  • dbms:作为逗号分隔列表给出的数据库类型。
  • global:定义属性是全局的还是仅限于数据库ChangeLog的。以truefalse表示。
<property name="simpleproperty" value="somevalue"/>
<property name="clob.type" value="clob" dbms="oracle,h2"/>
<property name="clob.type" value="longtext" dbms="mysql"/>
<property name="myproperty" value="yes" context="common,test"/>
<property name="localproperty" value="foo" global="false"/>
6.1.2.3、changeSet

changeset 标签是用于将数据库更改类型分组在一起的标记,并且是Liquibase在数据库上执行的更改单位。在changelog中跟踪由多个changeset 创建的变更列表。

每个changeSet标签都由id标签、author标签和changelogclasspath名称的组合唯一标签。id 标签仅用作标识符,它不指示更改运行的顺序,甚至不一定是整数。如果您不知道或不希望保存实际作者,只需使用占位符值,如UNKNOW

Liquibase执行数据库ChangeLog时,它按顺序读取changeSet,并针对每个changeSet检查databasechangelog表,以查看是否运行了 id/author/filepath的组合。如果已运行,则将跳过changeSet,除非存在真正的runAlways标签。运行changeSet中的所有更改后,Liquibase 将在databasechangelog中插入带有 id/author/filepath的新行以及changeSetMD5Sum(见下文)。

Liquibase 尝试执行每个changeSet并在每次结束时提交事务,或者如果出现错误,则回滚。某些数据库将自动提交语句,这些语句会干扰此事务设置,并可能导致意外的数据库状态。因此,通常最好每个changeSet只进行一次更改,除非有一组非自动提交更改要应用为事务(如插入数据)。

可用属性

  • id:字母数字标识符,必须
  • author:创建changeSet的人,必须
  • dbms:要用于changSet的数据库的类型。运行迁移步骤时,它会根据此属性检查数据库类型。有效的数据库类型名称列在受支持的数据库页上
  • runAlways:执行每次运行时设置的更改,即使更改之前已运行
  • runOnChange:在第一次看到更改时以及每次更改集更改时执行更改
  • context:如果在运行时传递了特定上下文,则执行更改。任何字符串都可用于上下文名称,并且它们处于不区分大小写状态。
  • runInTransaction:changeSet是否应作为单个事务运行(如果可能)?默认值为 true。从1.9开始,警告:小心使用此属性。如果设置为 false,并且通过运行包含多个语句的 changeSet部分发生错误,则 Liquibase 数据库更改日志表将保持无效状态。
  • failOnErroe:如果在执行changeSet时发生错误,是否认为此迁移失败?

可用的子标签

  • comment:changeSet的说明。XML 注释将提供相同的好处,Liquibase 的未来版本可能能够利用<comment>标记注释来生成文档

  • preConditions:将执行changeSet之前必须通过的前提条件。可用于在做不可恢复的内容(如自 1.7 起删除表)之前执行数据健全性检查

  • <AnyRefactoringTag(s)>:作为此changeSet的一部分运行的数据库更改(称为重构)

  • validCheckSum:列出被认为对此更改有效的校验,而不考虑数据库中存储的内容。自 1.7 起,主要用于需要修改changeSet,并且不希望在已运行过此修改的数据库上引发错误(不是建议的步骤)。

  • rollback:描述如何回滚changeSet的 SQL 语句或重构标签 PS:如何进行回滚操作,会在后面专门介绍。

6.1.2.4、include/includeAll

include 标签将 change-logs分解为几个更易于管理的部分。如果需要更容易地包含多个文件,请使用includeAll标签。

<?xml version="1.0" encoding="UTF-8"?>

<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.9"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.9
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.9.xsd">
    <include file="com/example/news/news.changelog.xml"/>
    <include file="com/example/directory/directory.changelog.xml"/>
</databaseChangeLog>


6.2、变更集(changeSet)

变更集,一个changeSet中可以有多个修改,每个changeSet都需要指定 id 和修改人(author),要求 id + author + filepath 必须唯一,id另外还可以指定上下文(context)、数据库系统(dbms)等信息。
Liquibase changeSet 常用属性(基于 liquibase-3.6)

属性名值类型默认值注释
idString(必需)修改集编号
authorString(必需)修改人
contextString修改上下文,指定后可以修改 springboot 配置文件中 spring.liquibase.context 项,来指定需执行的修改
labelsString标签,与 context 功能相同
dbmsString数据库系统,只用使用指定的数据库时才会执行,如 mysql、h2、postgresql、oracle等,多个数据库系统时以逗号分隔
alwaysRunBooleanfalse如果为 true 则每次 update 时都会执行
runOnChangeBooleanfalse如果未 true,则每次 checksum 改变时都会执行
ignoreBooleanfalse是否忽略此修改集
failOnErrorBooleantrue如果为 false ,在执行修改时出现错误,liquibase 不会停止,会继续执行其他修改
runInTransactionBooleantrue是否在执行时使用数据库事务管理
onValidationFail枚举,可选值:HALT、MARK_RANHALT验证失败后的处理方式,停止运行或记录运行状态

示例:

<databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd
        http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
    <changeSet id="20190314135820" author="wqf31415" context="dev" dbms="mysql"
               failOnError="true" onValidationFail="HALT"  >
		<!-- 修改集内容 -->
	</changeSet>
</databaseChangeLog>
6.2.1、创建表(createTable)

用于创建新的数据库表,写在 changeSet 标签内。
createTable 标签属性(基于 Liqubase-3.6)

属性名值类型默认值注释
tableNameString(必需)表名
catalogNameString目录名
schemaNameString数据库名
tablespaceString表空间
remarksString注释

示例:

<changeSet id="20190314135820" author="wqf31415" context="dev" dbms="mysql"
           failOnError="true" onValidationFail="HALT" labels="lab" ignore="false" runOrder="">
    <createTable tableName="changelog_example" catalogName="liquibase_demo" schemaName="liquibase_demo"
                 remarks="创建表changelog_example" tablespace="ts_changelog_example">
        <column name="id" type="bigint" autoIncrement="${autoIncrement}">
            <constraints primaryKey="true" nullable="false"/>
        </column>

        <column name="name" type="varchar(255)" remarks="姓名" >
            <constraints nullable="true" unique="true" uniqueConstraintName="unique_name"/>
        </column>

        <column name="active" type="bit" defaultValueBoolean="true" defaultValue="0">
            <constraints nullable="true" />
        </column>
    </createTable>
</changeSet>
6.2.1.1、列(column)

在创建表或给表添加列时,需要在 createTable 标签内添加 column 标签,用来指定列的属性。
column 标签常用属性

属性名值类型默认值注释
nameString字段名
typeString数据类型
defaultValueString默认值
autoIncrementBoolean自增
remarksString注释
6.2.1.2、约束(constraints)

在 column 标签中可以给字段添加约束,如可否为空、主键、唯一等约束条件。
constraints 标签常用属性

属性名值类型默认值注释
nullableBooleantrue可否为空
notNullConstraintNameString非空约束名
primaryKeyBoolean是否主键
primaryKeyNameString主键名
uniqueBooleanfalse是否唯一
6.2.2、添加字段(addColumn)

给已经创建的表添加字段,写在 changeSet 标签内,此标签内用 column 标签定义要添加的字段属性。

属性名值类型默认值注释
tableNameString(必需)表名
catalogNameString目录名
schemaNameString数据库名

示例:

<changeSet id="20190314154000" author="wqf" context="dev">
    <comment>增加 email 字段</comment>
    <addColumn tableName="changelog_example" catalogName="liquibase_demo" schemaName="liquibase_demo">
        <column name="email" type="varchar(255)">
            <constraints nullable="false"/>
        </column>
    </addColumn>
</changeSet>
6.2.3、删除字段(dropColumn)

dropColumn 标签用于删除已存在表中的字段,写在 changeSet 标签内,注意这个标签内部不能有内容,否则会报错。

属性名值类型默认值注释
tableNameString(必需)表名
nameString要删除的列名
catalogNameString目录名
schemaNameString数据库名

示例:

<changeSet id="20190314181622" author="wqf" context="dev">
       <comment>删除字段 name</comment>
       <dropColumn tableName="changelog_example" columnName="name" schemaName="liquibase_demo" catalogName="liquibase_demo"/>
   </changeSet>
6.2.4、插入数据(insert)

insert 标签用于在表中插入数据,写在 changeSet 标签内,需要指定表名等属性,在标签内使用 column 标签指定数据值。

属性名值类型默认值注释
tableNameString(必需)表名
dbmsString数据库类型,只有在指定的这种数据库下才会执行
catalogNameString目录名
schemaNameString数据库名

示例:

<changeSet id="20190314183320" author="wqf">
    <comment>插入数据</comment>
    <insert tableName="changelog_example" dbms="mysql" catalogName="liquibase_demo" schemaName="liquibase_demo">
        <column name="email" value="abc@abc.com"/>
        <column name="login_name" value="abc"/>
        <column name="password" value="abc123"/>
    </insert>
</changeSet>
6.2.5、加载批量数据(loadData)

在 changeSet 中添加 loadData 标签,用来加载数据。

属性名值类型默认值注释
tableNameString(必需)表名
fileString要加载的数据文件路径
separatorString分隔符
encodingString编码格式
quotcharString"引号
catalogNameString目录名
schemaNameString数据库名

示例:

<changeSet id="20190314183320" author="wqf">
      <loadData tableName="user" file="classpath:liquibase/initdata/user.csv" separator=";" encoding="UTF-8" 
                quotchar="&quot;" schemaName="liquibase_demo" catalogName="liquibase_demo"/>
</changeSet>
6.2.6、修改列名(renameColumn)

在 changeSet 中添加 renameColumn 标签用于修改列名。

属性名值类型默认值注释
tableNameString(必需)表名
oldColumnNameString原列名
newColumnNameString新列名
columnDataTypeString数据类型
remarksString注释
catalogNameString目录名
schemaNameString数据库名

示例:

<changeSet id="20190314184833" author="wqf">
    <comment>修改字段名</comment>
    <renameColumn tableName="changelog_example" oldColumnName="password" newColumnName="pwd" catalogName="liquibase_demo"
                  schemaName="liquibase_demo" columnDataType="varchar(255)" remarks="修改字段名"/>
</changeSet>
6.2.7、创建索引(createIndex)

为了提高数据查询速度,我们可以给关键字段添加索引,最好是在建表时就添加索引。如我们给 state 表的 collection_timedevice_id 字段添加联合索引,配置如下:

<changeSet id="201907100943" author="wqf">
    <createIndex tableName="state" indexName="index_collectionTime_deviceId">
        <column name="collection_time"></column>
        <column name="device_id"></column>
    </createIndex>
</changeSet>
6.2.8、添加数据库标签 (tagDatabase)

创建一个数据库标签以便将来回滚。

属性名值类型默认值注释
tagString标签名称
<changeSet  author="liquibase-docs"  id="tagDatabase-example">  
    <tagDatabase  tag="version_1.3"/>  
</changeSet>
6.2.9、Community Change Types

Change Types 是Liquibase对数据库架构所做的变更。

Liquibase Community 版可以进行以下类型的更改:

6.2.9.1、Changes that add something
Change Types释义
addAutoIncrement将现有的列转换为自动递增(也称为“身份”)列。
addColumnaddColumn更改类型将新列添加到现有表。
addDefaultValue将默认值添加到指定列的数据库定义中。必须设置defaultValue,defaultValueNumeric,defaultValueBoolean或defaultValueDate之一。
addForeignKeyConstraint将外键约束添加到现有列。
addLookupTable创建包含存储在列中的值的查找表,并创建新表的外键。
addNotNullConstraint向现有表添加非空约束。如果传递defaultNullValue属性,则在应用约束之前,列的所有空值都将更新为传递的值。
addPrimaryKey从现有列或一组列中添加主键。
addUniqueConstraint向现有列或一组列添加唯一约束。
6.2.9.2、Changes that create something
Change Types释义
createIndex在现有列或一组列上创建索引。
createProcedure定义存储过程的定义。此更改类型比原始SQL命令更适合用于创建过程,因为它不会尝试删除注释或拆分行。
createSequence创建一个新的数据库序列。
createTable创建一个表。
createView创建一个视图。
6.2.9.3、Changes that drop something
Change Types释义
dropAllForeignKeyConstraints删除全部外键约束
dropDefaultValue删除默认值
dropIndex删除索引
dropPrimaryKey删除主键
dropSequence删除序列
dropUniqueConstraint删除唯一约束
dropNotNullConstraint删除非空约束
dropProcedure删除存储过程
dropColumn删除列
dropForeignKeyConstraint删除指定的一个外键约束
dropTable删除表
dropView删除视图
6.2.9.4、Changes that rename something
Change Types释义
renameTable重命名表名
renameColumn重命名列名
renameView重命名视图名
renameSequence重命名序列名
6.2.9.5、SQL Changes
Change Types释义
sql执行指定 sql
sqlFile执行指定 SQL 文件中的 sql
6.2.9.6、Other kinds of changes
Change Types释义
delete从现有表中删除数据。
executeCommand执行系统命令。由于此更改类型不会像大多数情况下那样生成SQL,因此使用Liquibase命令(例如migrationSQL)可能无法按预期工作。因此,请尽可能使用生成SQL的更改类型。
loadData将数据添加到Changelog时,将数据从CSV文件加载到现有表中。
mergeColumns合并两个列中的值(以字符串形式连接),然后将结果值存储在新列中。
output记录消息并继续执行。
setTableRemarks为指定数据表添加备注
customChange自定义 Change
empty空,不执行任何操作
insert将数据插入到现有表中。
loadUpdateData将数据从CSV文件加载或更新到现有表中。通过发布检查记录是否存在的SQL批处理,不同于loadData。如果找到,则记录为UPDATE,否则记录为INSERTed。另外,生成DELETE语句以进行回滚。
modifyDataType修改数据类型
setColumnRemarks添加列注释
stop通过消息停止Liquibase执行。主要用于调试和逐步执行变更日志
update更新现有表中的数据。
alterSequence更改现有序列的属性。
tagDatabase创建一个数据库标签以便将来回滚。

7、Liquibase & Maven

7.1、在 Maven pom 文件配置 Liquibase

Maven中集成LiquiBase,主要是配置liquibase-maven-plugin,首先给出一个示例:

<plugin>
    <groupId>org.liquibase</groupId>
    <artifactId>liquibase-maven-plugin</artifactId>
    <version>3.4.2</version>
    <configuration>
        <propertyFileWillOverride>true</propertyFileWillOverride>
        <propertyFile>src/main/resources/liquibase/liquibase.properties</propertyFile>
        <changeLogFile>${changeLogFile}</changeLogFile>
        <driver>${driver}</driver>
        <url>${url}</url>
        <username>${username}</username>
        <password>${password}</password>
    </configuration>
    <executions>
        <execution>
            <phase>process-resources</phase>
            <goals>
                <goal>update</goal>
            </goals>
        </execution>
    </executions>
</plugin>

其中<configuration>节点中的配置可以放在单独的配置文件里。

changeLogFile:src/main/resources/liquibase/master.xml
driver:com.mysql.cj.jdbc.Driver
url:jdbc:mysql://localhost:3306/test
username:root
password:aries2776

7.2、liquibase:update

执行changelog中的变更:

mvn liquibase:update

7.3、liquibase:rollback

rollback有3中形式,分别是:

  • rollbackCount: 表示rollback的changeset的个数;
  • rollbackDate:表示rollback到指定的日期;
  • rollbackTag:表示rollback到指定的tag,需要使用LiquiBase在具体的时间点打上tag;可以在 changeLog 文件中显式定
7.3.1、rollbackCount

rollbackCount比较简单,示例如:

mvn liquibase:rollback -Dliquibase.rollbackCount=3

回滚指定数量的 changeSet

7.3.2、rollbackDate

rollbackDate需要注意日期的格式,必须匹配当前平台上执行DateFormat.getDateInstance()得到的格式,比如我的格式为MMM d, yyyy,示例如:

mvn liquibase:rollback -Dliquibase.rollbackDate="Apr 10, 2016"
7.3.3、rollbackTag

rollbackTag使用tag标识,所以需要先打tag,示例如:

mvn liquibase:tag -Dliquibase.tag=tag20160410

或者

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

    <!-- 创建 tag -->
    <changeSet id="8" author="aries">
        <tagDatabase tag="20201210-before-tag" />
    </changeSet>

    <changeSet id="7" author="aries">
        <createTable tableName="entity">
            <column name="entity_id" autoIncrement="1" type="int">
                <constraints primaryKey="true" nullable="false" unique="true"/>
            </column>
            <column name="name" type="varchar(200)" />
            <column name="tenant_api_name" type="varchar(200)" />
            <column name="api_name" type="varchar(200)" />
            <column name="entity_type" type="varchar(200)" />
            <column name="primary_key_field" type="varchar(200)" />
            <column name="status" type="int(11)" />
            <column name="params" type="json" />
            <column name="b_time_field" type="varchar(200)" />
        </createTable>
    </changeSet>

</databaseChangeLog>

回滚操作:

mvn liquibase:rollback -Dliquibase.rollbackTag=20201210-before-tag

7.4、liquibase:generateChangeLog

<build>
	<plugins>
		<plugin>
			<groupId>org.liquibase</groupId>
			<artifactId>liquibase-maven-plugin</artifactId>
			<version>3.4.2</version>
			<configuration>
				<propertyFile>src/main/resources/liquibase.properties</propertyFile>
				<propertyFileWillOverride>true</propertyFileWillOverride>
				<!--生成文件的路径-->
				<outputChangeLogFile>src/main/resources/changelog_dev.xml</outputChangeLogFile>
			</configuration>
		</plugin>
	</plugins>
</build>
mvn liquibase:generateChangeLog
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值