使用liquibase-maven-plugin实现持续数据库集成
数据库版本管理、持续集成一直都是大家比较关心的问题,网上也有很多相关的文章介绍。一直都很羡慕ruby on rails的database migration,非常强大,好在java阵营也有类似的工具可以帮助大家管理数据库版本,实现数据库迁移。本文将针对liquibase-maven-plugin这个maven插件做详细的介绍,希望能对大家有所帮助。
一、配置properties-maven-plugin,使maven加载外部属性配置文件
liquibase需要配置数据库的连接属性及驱动等参数,如果这些参数直接配置在pom文件中,会增加配置管理人员的工作量,因此希望能够统一读取web应用中已经配置好的properties文件中的配置属性,可以使用properties-maven-plugin插件导入配置文件,配置示例如下:
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>properties-maven-plugin</artifactId> <version>1.0-alpha-2</version> <executions> <execution> <phase>initialize</phase> <goals> <goal>read-project-properties</goal> </goals> <configuration> <files> <file>${basedir}/src/main/resources/conf/geoq.properties</file> </files> </configuration> </execution> </executions> </plugin>
geoq.properties配置示例如下:
jdbc.driverClassName=org.postgresql.Driver jdbc.url=jdbc:postgresql://localhost:5432/geoq_dev jdbc.username=postgres jdbc.password=4652
那么就可以在pom中使用${PropertyNmae}引用配置属性,如
<configuration> <changeLogFile>src/main/resources/liquiabse/business_table.xml</changeLogFile> <driver>${jdbc.driverClassName}</driver> <url>${jdbc.url}</url> <username>${jdbc.username}</username> <password>${jdbc.password}</password> </configuration>
二、配置liquibase-maven-plugin
配置示例如下:
<plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>2.0.5</version> <dependencies> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>2.0.5</version> </dependency> </dependencies> <executions> <execution> <phase>process-resources</phase> <configuration> <changeLogFile>src/main/resources/liquiabse/business_table.xml</changeLogFile> <driver>${jdbc.driverClassName}</driver> <url>${jdbc.url}</url> <username>${jdbc.username}</username> <password>${jdbc.password}</password> </configuration> <goals> <goal>update</goal> </goals> </execution> </executions> </plugin>
1、需要通过dependency引入依赖jar包liquibase-core,版本号与插件版本号一致
2、通过phase参数指定何时运行,一般为process-resources
3、changeLogFile参数指定liquibase数据库变更日志文件
4、driver、url、username、password配置数据库连接参数
三、根据数据库生成数据库变更日志文件
针对已有的数据库,如何产生对应的数据库变更日志文件,可以使用generateChangeLog指令,使用该指令需要下载liquibase的执行程序,命令示例如下:
liquibase --driver=org.postgresql.Driver --classpath="C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-9.1-901.jdbc4.jar" --changeLogFile=db.changelog.xml --url="jdbc:postgresql://localhost:5432/geoq_dev" --username=postgres --password=4652 generateChangeLog
generateChangeLog默认只会创建数据库结构的变更日志文件,如果希望创建插入数据的变更日志文件,可以使用参数diffTypes,该参数包括如下可选项:
- tables [DEFAULT]表
- columns [DEFAULT] 列
- views [DEFAULT] 视图
- primaryKeys [DEFAULT] 主键
- indexes [DEFAULT] 索引
- foreignKeys [DEFAULT]
- sequences [DEFAULT]
- data
liquibase --driver=org.postgresql.Driver --classpath="C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-9.1-901.jdbc4.jar" --changeLogFile=db.changelog.xml --url="jdbc:postgresql://localhost:5432/geoq_dev_full" --username=postgres --password=4652 --diffTypes=data generateChangeLog
比较两个数据库:
liquibase --driver=org.postgresql.Driver --classpath="C:\Program Files (x86)\PostgreSQL\pgJDBC\postgresql-9.1-901.jdbc4.jar" --changeLogFile=db.changelog.xml --url="jdbc:postgresql://localhost:5432/geoq_dev" --username=postgres --password=4652 diffChangeLog --referenceUrl="jdbc:postgresql://localhost:5432/geoq_dev_full" --referenceUsername=postgres --referencePassword=4652
四、对现有数据库进行重构
数据库变更日志文件可以对数据库的变更进行版本管理,并且可以摆脱对特定数据库的依赖,因此需要了解数据库变更日志文件的相关语法,下面分别介绍如何通过数据库变更日志配置数据库重构。
1、编辑列:
添加列
<changeSet id="4" author="joe"> <addColumn tableName="distributor"> <column name="phonenumber" type="varchar(255)"/> </addColumn> </changeSet>
添加自增列:
<column autoIncrement="true" name="module_config_id" type="int" startWith="1"> <constraints nullable="false" primaryKey="true" primaryKeyName="pk_t_module_config"/> </column>
删除列:
<dropColumn tableName="distributor" columnName="phonenumber"/>
修改已存在的列为自增列
<addAutoIncrement tableName="person" columnName="id" columnDataType="int"/>
修改postgresql自增列当前索引值:liquibase不支持该操作,可以使用sql标签实现
<sql> ALTER SEQUENCE t_role_role_id_seq RESTART WITH 3; </sql>
2、创建表:
<changeSet id="3" author="betsey"> <createTable tableName="distributor"> <column name="id" type="int"> <constraints primaryKey="true" nullable="false"/> </column> <column name="name" type="varchar(255)"> <constraints nullable="false"/> </column> <column name="address" type="varchar(255)"> <constraints nullable="true"/> </column> <column name="active" type="boolean" defaultValue="1"/> </createTable> </changeSet>
3、操作数据:
<changeSet id="3" author="betsey"> <code type="section" width="100%"> <insert tableName="distributor"> <column name="id" valueNumeric="3"/> <column name="name" value="Manassas Beer Company"/> </insert> <insert tableName="distributor"> <column name="id" valueNumeric="4"/> <column name="name" value="Harrisonburg Beer Distributors"/> </insert> </changeSet>
应该编写用于操作数据的 SQL 脚本,因为使用 LiquiBase XML 变更集限制很多。有时候使用 SQL 脚本向数据库应用大量的变更会简单一些。LiquiBase 也可以支持这些情景。
如下例为从 LiquiBase 变更集运行一个定制 SQL 文件
<changeSet id="6" author="joe"> <sqlFile path="insert-distributor-data.sql"/> </changeSet>
编写changeset时,如果字段的内容为html标签,可以使用<![CDATA[html tag]]符号导入带有html标签的文本。
4、操作序列:
创建序列
<createSequence sequenceName="seq_employee_id"/>
sequenceName |
序列名称 [required] |
schemaName |
表schema名称 |
incrementBy |
自增间隔值 |
minValue |
序列的最小值 |
maxValue |
序列的最大值 |
ordered |
'true' 或者 'false' |
startValue |
序列的起始值 |
修改序列
<alterSequence sequenceName="seq_employee_id" incrementBy="10"/>
sequenceName |
序列的名称 [required] |
incrementBy |
新的自增间隔值 [required] |
五、liquibase-maven-plugin基本命令
- 更新数据库:mvn liquibase:update
- 打版本标签:mvn liquibase:tag
- 回滚到最近的更新版本,或指定的标签版本,或日期,或更新次数:mvn liquibase:rollback -Dliquibase.rollbackCount=1
- 生成sql更新脚本:mvn liquibase:updateSQL
六、数据库版本控制
1、添加版本标签:
a、使用命令行:
mvn liquibase:tag -Dliquibase.tag=checkpoint
b、使用配置文件:
<executions> <execution> <phase>process-resources</phase> <configuration> <tag>${project.version}</tag> </configuration> <goals> <goal>update</goal> <goal>tag</goal> </goals> </execution> </executions>
2、可以使用如下命令回滚到某个版本:
mvn liquibase:rollback -Dliquibase.rollbackTag=checkpoint
对应的maven配置为:
<executions> <execution> <phase>process-resources</phase> <configuration> <changeLogFile>src/main/resources/liquiabse/master-changelog.xml</changeLogFile> <driver>${jdbc.driverClassName}</driver> <url>${jdbc.url}</url> <username>${jdbc.username}</username> <password>${jdbc.password}</password> <rollbackTag>1.1</rollbackTag> </configuration> <goals> <goal>update</goal> <goal>rollback</goal> </goals> </execution> </executions>
rollback操作可选参数包括:
String |
设置Liquibase变更集文件 |
|
boolean |
标识是否强制清除数据库表校验. 默认值为:false. |
|
String |
配置Liquibase执行的上下文,多个上下文可以使用逗号分隔 |
|
String |
数据库对象的类 |
|
String |
数据库连接使用的默认数据库结构名称 |
|
String |
数据库连接的驱动名称 |
|
boolean |
已过期。是否使用空字符串或null作为数据库连接密码 默认值为:false. |
|
Map |
传递给插件的数组变量 |
|
Properties |
传递给插件的数组变量 |
|
boolean |
是否允许为获取Liquibase属性或数据库变更日志时包含maven项目组件 默认值为:true. |
|
boolean |
是否允许为获取Liquibase属性或数据库变更日志时包含测试输出目录 默认值为:true. |
|
String |
控制插件输出的日志级别。 可选值包括:"all", "finest", "finer", "fine", "info", "warning", "severe" or "off",注意该值是区分大小写的。 默认值为:INFO. |
|
String |
数据库连接密码 |
|
boolean |
是否允许控制用户执行远程数据库 |
|
String |
Liquibase属性文件位置 |
|
boolean |
标志是否允许使用Liquibase属性文件覆盖插件的配置 默认值为:false. |
|
int |
回滚的变更集个数 默认值为:-1. |
|
String |
设置回滚的日期。日期格式要符合插件执行theDateFormat.getDateInstance()操作设置的日期格式 |
|
String |
要回滚到那个tag |
|
String |
在settings.xml中的服务器id进行身份验证时使用 |
|
boolean |
设置为“true”跳过运行liquibase,该参数不推荐使用 |
|
Properties |
传递到数据库的系统属性 |
|
String |
数据库连接地址 |
|
String |
用户名称 |
|
boolean |
控制调用插件的输出的详细程度。 默认值为:false. |
也可以指定回滚的步数(changeset个数):
mvn liquibase:rollback -Dliquibase.rollbackCount=3
或者生成回滚的sql脚本:
mvn liquibase:rollbackSQL -Dliquibase.rollbackTag=checkpoint
3、可以根据不同的版本分别创建相关changelog文件,使用include标签分别引入,如主干changelog文件为master-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" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-2.0.xsd"> <include file="src/main/resources/liquibase/liquibase-create-tables.xml" /> <include file="src/main/resources/liquibase/liquibase-insert-data.xml" /> <include file="src/main/resources/liquibase/liquibase-mobile-menu.xml" /> …... <include file="src/main/resources/liquibase/liquibase-update-to-1.4.xml"/> <include file="src/main/resources/liquibase/liquibase-update-to-1.6.xml"/> …... </databaseChangeLog>
七、创建特殊的类型的字段
在changelog文件中,如希望创建postgresql支持的enum,可以使用的方法如下:
1、使用sql脚本直接创建
<changeSet id="1" author="Arthur"> <sql>CREATE TYPE my_state AS ENUM ('yes','no')</sql> <table name="foo"> <column name="state" type="my_state"/> </table> </changeSet>
2、使用约束
<changeSet id="1" author="X"> <table name="t"> <column name="c" type="varchar(3)"/> </table> <sql>ALTER TABLE t ADD CONSTRAINT check_yes_no CHECK (c = 'yes' OR c = 'no')</sql> </changeSet>
3、获取系统当前时间
首先定义不同数据库获取时间的属性标签
<property name="now" value="sysdate" dbms="oracle"/> <property name="now" value="now()" dbms="mysql"/>
在changesets中引用该属性
<column name="Join_date" defaultValueFunction="${now}"/>
完整示例如下:
<property name="now" value="UNIX_TIMESTAMP()" dbms="mysql"/> <changeSet id="emp_1" author="Me"> <insert tableName="Emp" schemaName="XYZ"> <column name="EmpName" value="abc"/> <column name="Join_date" valueDate="${now}"/> <column name="Profile_last_update" valueDate="${now}"/> <column name="group_name" value="BlahBlah"/> </insert> </changeset>
八、支持多数据库
可以在pom文件使用多个execution标签支持多数据库,但是需要注意每个execution一定要定义id标签
<plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-plugin</artifactId> <version>1.9.5.0</version> <executions> <execution> <phase>process-resources</phase> <configuration> <changeLogFile>src/main/resources/db.changelog.xml</changeLogFile> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://localhost:3306/charm</url> <username>***</username> <password>***</password> </configuration> <goals> <goal>update</goal> </goals> </execution> <execution> <phase>process-resources</phase> <configuration> <changeLogFile>src/main/resources/db.changelog.xml</changeLogFile> <driver>com.mysql.jdbc.Driver</driver> <url>jdbc:mysql://localhost:3306/charm2</url> <username>***</username> <password>***</password> </configuration> <goals> <goal>update</goal> </goals> </execution> </executions> </plugin>
九、参考网站
帮助手册:http://www.liquibase.org/manual/home
properties-maven-plugin手册:http://www.liquibase.org/manual/maven