参考资料:
LiquiBase是一个用于数据库重构和迁移的开源工具,通过日志文件的形式记录数据库的变更,然后执行日志文件中的修改,将数据库更新或回滚到一致的状态。它的目标是提供一种数据库类型无关的解决方案,通过执行schema类型的文件来达到迁移。
LiquiBase的主要特点有:
为什么使用liquibase?
在日常的项目开发中,开发团队经常将数据库和应用程序视为单独的实体,这样就导致了数据库团队与应用开发团队分离造成团队之间信息交流不畅,信息交流不及时,这种情况通常表现为下面几种行为:
上面的几种行为都是我们在实际开发中遇到的问题,不仅效率低而且出错的机会也高,就算是老司机也会翻车。
解决上面问题的思路是:减少人工手工变更数据库的机会,用程序管理数据库版本的更替。
changelog是LiquiBase用来记录数据库的变更,一般放在CLASSPATH下,然后配置到执行路径中。
changelog支持多种格式,主要有XML/JSON/YAML/SQL,其中XML/JSON/YAML除了具体格式语法不同,节点配置很类似,SQL格式中主要记录SQL语句,这里仅给出XML格式的示例,更多的格式示例请参考文档
changelog.xml
一个标签对应一个变更集,由属性id、name,以及changelog的文件路径唯一标识。changelog在执行的时候并不是按照id的顺序,而是按照changeSet在changelog中出现的顺序。
每个更改集都用“id”属性和“author”属性唯一标识。“作者”属性可以最大限度地减少重复的可能性。
liquibase将每个更改集视为要应用于数据库的原子更改。通常最好只在更改集中包含一个更改。
changelog中的一个changeSet对应一个事务,在changeSet执行完后commit,如果出现错误则rollback。
liquibase 可以使用命令行 Ant Maven Spring等工具运行。
下面是一个mysql下执行的例子:
liquibase --driver=com.mysql.jdbc.Driver \
--classpath=/path/to/classes \
--changeLogFile=com/example/db.changelog.xml \
--url="jdbc:mysql://localhost/example" \
--username=user \
--password=asdf \
update
你可以看到数据库现在包含一个名为“department”的表。还创建了另外两个表:“databasechangelog”和“databasechangeloglock”。
后面数据库如果有变动,可以再生成新的changelog文件,再次添加到项目中,达到持续集成的效果。
org.liquibase
liquibase-core
3.5.3
package com.aop8.config;
import javax.sql.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import liquibase.integration.spring.SpringLiquibase;
@Configuration
public class LiquibaseConfig {
@Bean
public SpringLiquibase liquibase(DataSource dataSource) {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(dataSource);
//指定changelog的位置,这里使用的一个master文件引用其他文件的方式
liquibase.setChangeLog("classpath:config/liquibase/master.xml");
liquibase.setContexts("development,test,production");
//如果设置为true:第一次执行不会报错,第二次将会报错,导致程序无法启动,所以第一次执行完后一定要改为:false
liquibase.setShouldRun(true);
return liquibase;
}
}
路径:src/main/resources 目录下 config/liquibase/master.xml
与
标签
的file属性表示要包含的changelog文件的路径,这个文件可以是LiquiBase支持的任意格式,relativeToChangelogFile如果为true,则表示file属性表示的文件路径是相对于根changelog而不是CLASSPATH的,默认为false。
指定的是changelog的目录,而不是为文件,如:
注意: 目前
没有解决重复引用和循环引用的问题,重复引用还好,LiquiBase在执行的时候可以判断重复,而循环引用会导致无限循环,需要注意!
路径:
src/main/resources 目录下
config/liquibase/changelog/201712022057_add_entity_Base.xml
LiquiBase 支持很多其他数据库重构,如
添加列
删除列
使用一个 LiquiBase 变更集插入数据
changelogSync : 將changelog中未套用至db的change logs标识成已同步
changelogSyncSQL : 同changelogSync,但只產生sql,而不執行同步到db
generateChangeLog : 將目前数据库的结构(默认不包含数据)生成 changeLog 文件
dbDoc : 產生像java doc的文件
diff : 比對兩個数据库間的差異
status : 顯示目前change set有那些change log會被套用到db
rollbackSql:根据回滚版本生成回滚sql
rollback:根据回滚版本生成回滚sql,并在数据库中执行
update : 将changeLog.xml中的数据变动changeset脚本转化为sql语句,直接在数据库中执行
updateSQL : 将changeLog.xml中的数据变动changeset脚本转化为sql语句,并输出到对应的文件中
dropAll : 清空当前数据库,包括liquibase的版本信息
tag : 为当前数据库打上标签
生成已有数据库的changelog有两种方式,一种是使用数据库工具导出SQL数据,然后changelog文件以SQL格式记录即可;另一种方式就是用generateChangeLog命令,如:``
liquibase --driver=com.mysql.jdbc.Driver \
--classpath=./mysql-connector-java-5.1.29.jar \
--changeLogFile=liquibase/db.changelog.xml \
--url="jdbc:mysql://127.0.0.1:3306/test" \
--username=root \
--password=yourpass \
generateChangeLog
generateChangeLog命令默认只会创建数据库结构的变更日志文件,如果希望创建插入数据的变更日志文件,可以使用参数diffTypes,该参数包括如下可选项:
例如生成数据:
liquibase --driver=com.mysql.jdbc.Driver --classpath=mysql-connector-java-5.1.27.jar --changeLogFile=./dbchangelog.xml --url="jdbc:mysql://localhost:3306/blog" --username=root --password=root --diffTypes=data generateChangeLog
分别生成了两个changeLog文件,一个是inti-table.xml; 一个是init-data.xml。
不过generateChangeLog不支持以下功能:存储过程、函数以及触发器;
生成文件的路径可以设置:
org.liquibase
liquibase-maven-plugin
3.5.1
src/main/resources/liquibase/liquibase.properties
src/main/resources/liquibase/master.xml
src/main/resources/changelog_dev.xml
false
UTF-8
true
true
${project.version}
${project.version}
也可以配置在properties文件中:
changeLogFile=src/main/resources/db/changelog/db.changelog-master.xml
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&useSSL=false&jdbcCompliantTruncation=false
username=rootpassword=123456
verbose=true\## 生成文件的路径
outputChangeLogFile=src/main/resources/changelog_dev.xml
rollback有3中形式,分别是:
liquibase:rollback -Dliquibase.rollbackCount=3
rollbackDate需要注意日期的格式,必须匹配当前平台上执行DateFormat.getDateInstance()得到的格式,比如格式为MMM d, yyyy,示例如:
liquibase:rollback -Dliquibase.rollbackDate="Apr 10, 2016"
rollbackTag使用tag标识,所以需要先打tag,示例如:
liquibase:tag -Dliquibase.tag=tag20160410
然后rollback到tag20160410,如:
liquibase:rollback -Dliquibase.rollbackTag=tag20160410
时,禁止包含schema名称使用Liquibase中提供
标签,可以将ChangeSet分布在不同文件中。同时
支持多级引用。
基于此功能可以对项目中的ChangeSet进行有效管理。推荐使用以下规范进行管理。
resources
|-liquibase
|-user
| |- master.xml
| |- release.1.0.0
| | |- release.xml
| | |- user.xml -- 用户相关表ChangeSet
| | |- user.csv -- 用户初始化数据
| | |- company.xml -- 公司相关表ChangeSet
| |- release.1.1.0
| | |- release.xml
| | |- ...