通过Maven用LiquiBase对数据库变更进行版本控制
source link: https://www.pkslow.com/archives/liquibase
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
1 LiquiBase是什么
1.1 概述与特点
LiquiBase
是用于跟踪、管理和应用数据库变更的开源工具,它把数据库的变更记录在文件(xml/sql等)中,然后把变更作用到数据库中,并记录。我觉得它的主要特点:
(1)它支持多种数据库,如Oracle/MySQL/PostgreSQL/DB2
等;
(2)提供数据库比较功能,把结果存在xml
中,然后可基于该xml
升级;
(3)会在数据库中保存修改历史,可查看记录、可支持回滚(按标签、数量和时间);已经升级的变更不会再操作;
(4)可通过maven
集成,方便CI/CD
;
1.2 基本概念
(1)change log
文件,用于记录数据库变更(changeset);可以把变更记录在xml
文件、sql
文件等;
(2)changeset
,变更集,作为一次变更的单位,可以是新建一张表、加一列,插入数据、删除索引等。升级与回滚都是以changeset
为单位的;每个changeset
会通过id
和author
来标记。
(3)DATABASECHANGELOG
表用于记录被执行过的changeset
,当回滚后,就会删去被回滚掉的记录,下表有6条记录,表示有6个changeset
被执行了。记录了很多关键信息,如作者、所在文件、执行时间等。
2 项目整合
LiquiBase
有命令行工具,但本文主要介绍通过maven
来操作。之前文章《Docker启动PostgreSQL并推荐几款连接工具》介绍了如何快速安装PostgreSQL
,那我们这次就用它作为数据库。
2.1 maven配置
主要通过maven
的插件来执行变更,所以要引入LiquiBase
的插件,及配置相关属性如下:
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>4.1.1</version>
<configuration>
<propertyFileWillOverride>true</propertyFileWillOverride>
<propertyFile>target/classes/liquibase/properties/liquibase.properties</propertyFile>
</configuration>
<dependencies>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.18</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
这里还要引入PostgreSQL
是因为需要它的数据库驱动。
2.2 属性配置文件
运行LiquiBase
需要传递一些参数,如文件名、数据库连接信息等,所以liquibase.properties
的内容如下:
changeLogFile: src/main/resources/liquibase/db.changelog.xml
driver: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/pkslow
username: pkslow
password: pkslow
verbose: true
dropFirst: false
2.3 数据库变更文件
变更文件db.changelog.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.8.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd">
<changeSet id="1" author="larry">
<createTable tableName="person">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true" nullable="false"/>
</column>
<column name="firstname" type="varchar(50)"/>
<column name="lastname" type="varchar(50)">
<constraints nullable="false"/>
</column>
<column name="state" type="char(2)"/>
</createTable>
<rollback>
<dropTable tableName="person"/>
</rollback>
</changeSet>
<changeSet id="2" author="larry">
<addColumn tableName="person">
<column name="username" type="varchar(8)"/>
</addColumn>
<rollback>
<dropColumn tableName="person">
<column name="username"/>
</dropColumn>
</rollback>
</changeSet>
</databaseChangeLog>
这个文件定义了两个变更集,第一个用于创建表person
,第二个用于加字段username
,同时提供了rollback
语句以支持回滚。
准备好以上文件后,执行以下命令便可以使变更生效:
mvn clean package liquibase:update
查看数据库如下:
新建了一个person
表,并有字段username
。
因为执行了两个变更集,所以如果我想要回滚所有变更,命令如下:
mvn liquibase:rollback -Dliquibase.rollbackCount=2
3 进阶使用
LiquiBase
很强大,有很多强大的用法,这里选几个我觉得很有用的介绍一下。
3.1 执行条件判断
在change log
文件中,可以指定前置判断条件,如下:
<preConditions>
<dbms type="oracle"/>
<runningAs username="pkslow"/>
</preConditions>
这样表示数据库为Oracle
,数据库的用户名为pkslow
才允许执行。可以防止配置错误和升级错误。
3.2 多环境属性文件
通常我们的数据库都是与多个环境对应的,如dev
、uat
、prod
等。我们可以通过maven
的变量来指定环境:
<properties>
<liquibase.env>dev</liquibase.env>
</properties>
<propertyFile>target/classes/liquibase/properties/liquibase.${liquibase.env}.properties</propertyFile>
默认值为dev
,然后可以通过传参指定其它:
mvn clean package liquibase:update -Dliquibase.env=uat
这样它就能匹配到下面对应的文件:
liquibase.dev.properties
liquibase.uat.properties
liquibase.prod.properties
3.3 多种文件嵌套使用
LiquiBase
可以嵌套文件,如xml
嵌套xml
文件或sql
文件:
<include file="xml/pkslow.person.xml" relativeToChangelogFile="true"/>
<include file="sql/pkslow.student.sql" relativeToChangelogFile="true"/>
<include file="sql/pkslow.order.sql" relativeToChangelogFile="true"/>
其实还支持yaml
和json
等,但我觉得还是xml
或sql
更适用。
3.4 多环境动态标识替换
不同数据库字段标识是不一样的,语法也会有不同,通过定义属性,能解决这个问题:
<property name="clob.type" value="clob" dbms="oracle,postgresql"/>
<property name="clob.type" value="longtext" dbms="mysql"/>
<property name="table.name" value="tableA"/>
<changeSet id="1" author="joe">
<createTable tableName="${table.name}">
<column name="id" type="int"/>
<column name="column1" type="${clob.type}"/>
<column name="column2" type="int"/>
</createTable>
</changeSet>
3.5 密码加密
把数据库密码以明文形式配置在文件中不是什么好习惯,LiquiBase
提供了替换属性类的功能,可以用来实现加密解密:
<configuration>
<propertyFileWillOverride>true</propertyFileWillOverride>
<propertyFile>target/classes/liquibase/properties/liquibase.${liquibase.env}.properties</propertyFile>
<propertyProviderClass>com.pkslow.liquibase.PkslowLiquibaseProperties</propertyProviderClass>
</configuration>
propertyProviderClass
就是用来加密的类,如下:
package com.pkslow.liquibase;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import java.util.Properties;
public class PkslowLiquibaseProperties extends Properties {
private static final StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
static {
System.out.println("init for encryptor");
//设置密钥
encryptor.setPassword("pkslow-salt");
//设置加密算法
encryptor.setAlgorithm("PBEWithMD5AndTripleDES");
}
@Override
public synchronized Object put(Object key, Object value) {
if ("password".equals(key)) {
value = encryptor.decrypt((String) value);
}
return super.put(key, value);
}
}
如果想,还可以加密其它字段。
3.6 强大的回滚能力
LiquiBase
提供了按数量、日期和标签回滚的能力,如下:
# 按数量回滚,2表示回滚两个changeset
mvn liquibase:rollback -Dliquibase.rollbackCount=2
# 按日期回滚
mvn liquibase:rollback "-Dliquibase.rollbackDate=Jun 03, 2017"
# 按标签回滚
mvn liquibase:rollback -Dliquibase.rollbackTag=V1.0
这里我觉得最实用的是按标签回滚功能。
每次版本升级,就打上一个标签,如V1.0
、V1.1
、V2.0
等,如果有问题,就回滚至对应标签(版本)。添加标签命令如下:
mvn liquibase:tag -Dliquibase.tag=V1.1
我把三个文件分三次升级,打了三个tag
如下:
现在回滚到V1.1
如下:
mvn liquibase:rollback -Dliquibase.rollbackTag=V1.1
结果如下:
相信本文能帮助大家理解和使用LiquiBase
,代码请查看:https://github.com/LarryDpk/pkslow-samples
参考资料:
Jasypt加密:如何使用优秀的加密库Jasypt来保护你的敏感信息?
XML标签:https://docs.liquibase.com/change-types/community/home.html
多种格式参考:Changelog
maven
整合指导:Maven
另一种整合方式,把密码信息保存在settings.xml里:Liquibase with Maven
其它用法:The Magic of Using XML Changelogs in Liquibase
参数参考:LiquiBase 管理数据库变更实践
欢迎关注微信公众号<南瓜慢说>,将持续为你更新...
推荐阅读:
如何制定切实可行的计划并好好执行
容器技术(Docker-Kubernetes)
SpringBoot-Cloud相关
Https专题
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK