數據庫版本管理、持續集成一直都是大家比較關心的問題,網上也有很多相關的文章介紹。一直都很羡慕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