說明
項目升級時,數據庫的變更手動維護很麻煩,而且容易出錯,liquibase是一個很好的工具,liquibase與maven集成後,每次升級時將sql腳本添加到liquibase的數據變更日誌文件中(changelog.xml),在maven編譯時就會自動執行升級腳本,非常方便。
maven配置
配置maven插件
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
pom.xml詳細配置如下:其中changeLogFile
指定數據變更日誌文件的路徑
<build>
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.6.3</version>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
</dependencies>
<configuration>
<!-- skip 是否跳過該插件,
如果是開發環境則設置成true,不執行腳本變更,
生產/測試環境則設置爲false(執行腳本變更),
可以在profile中注入liqubase.skip變量來控制,不同環境使用不同profile即可 -->
<skip>${liqubase.skip}</skip>
<verbose>true</verbose>
<logging>debug</logging>
<!-- 配置【數據變更日誌文件】的路徑 -->
<changeLogFile>src/main/resources/liquibase/changelog.xml</changeLogFile>
<!-- jdbc驅動 -->
<driver>com.mysql.jdbc.Driver</driver>
<!-- 數據庫連接連接配置 -->
<!-- <url>${mybatis.generator.jdbcURL}${mybatis.generator.schema}</url> -->
<url>jdbc:mysql://localhost:3306/useUnicode=true&characterEncoding=utf8&useSSL=false</url>
<!-- schema配置 -->
<defaultSchemaName>test</defaultSchemaName>
<!-- 數據庫用戶名/密碼等配置 -->
<username>root</username>
<password>123456</password>
<contexts>local</contexts>
<!-- 靜默執行 -->
<promptOnNonLocalDatabase>false</promptOnNonLocalDatabase>
</configuration>
<executions>
<execution>
<phase>process-resources</phase>
<goals>
<!-- update 表示去執行腳本更新 -->
<goal>update</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
maven配置詳見官網:http://www.liquibase.org/documentation/maven/index.html
數據變更日誌文件支持多種格式,如 xml,sql,json,yaml 等,changelog.xml就是xml格式的,由於xml格式有特定的語法規則來支持數據的DDL和DML,如果不是多數據源的數據遷移(比如Oracle到mysql),不用考慮數據庫方言的差異,一般直接使用sql格式。
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">
<preConditions>
<runningAs username="liquibase"/>
</preConditions>
<!-- 每一個changeSet表示一個變更單元,可以配置多個
id: changeset標識,規則自定義,可以模仿版本號的形式(方便管理),也可以直接用自增序列 1,2,3...
author:作者署名
-->
<changeSet id="v01.00.00-1" author="nvoxland">
<!-- createTable表示創建一張表,tableName指定表名 -->
<createTable tableName="person">
<!-- column用於配置數據表的字段,name指定字段名,type指定字段類型 -->
<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>
</changeSet>
<changeSet id="v01.00.00-2" author="nvoxland">
<addColumn tableName="person">
<column name="username" type="varchar(8)"/>
</addColumn>
</changeSet>
<changeSet id="v01.00.00-3" author="nvoxland">
<addLookupTable
existingTableName="person" existingColumnName="state"
newTableName="state" newColumnName="id" newColumnDataType="char(2)"/>
</changeSet>
</databaseChangeLog>
sql 格式如下:該示例來自官方文檔
--liquibase formatted sql
必須以這個開頭 ,
--changeset [author]:[id]
與xml中的<changeSet>
功能相同,表示一個變更單元,下一行直接寫sql腳本,
--rollback
可以配置回滾,changset執行失敗時可以進行回滾,如果沒有直接用 --rollback not required;
--liquibase formatted sql
--changeset nvoxland:v01.00.00-1
create table person (
id int not null primary key,
firstname varchar(80),
lastname varchar(80) not null,
state varchar(2)
);
--rollback not required;
--changeset nvoxland:v01.00.00-2
alter table person add column username varchar(8)
--rollback not required;
--changeset nvoxland:v01.00.00-3
create table state AS SELECT DISTINCT state AS id FROM person WHERE state IS NOT NULL;
alter table state modify id char(2) NOT NULL;
alter table state add primary key(id);
alter table person add constraint fk_person_state foreign key (state) references state(id);
--rollback not required;
這裏使用xml格式結合sql格式使用 ,changelog.xml 做簡單配置(無需配置changeset執行腳本,腳本配置在sql格式的文件中),
在xml中使用include來包含sql格式的文件即可,如下可以將多個xxx.sql文件放在liquibase/update/
目錄,
比如每次升級用一個單獨的sql文件,方便維護。
類似這種:v0.1.sql , v0.2.sql , v0.3.sql …
<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">
<!-- 相對於當前項目classpath的路徑(編譯後:${project.basedir}/target/classes 源碼:${project.basedir}/src/main/resources) -->
<includeAll path="liquibase/update/"></includeAll>
</databaseChangeLog>
目錄結構如下:
liquibase的數據表
第一次maven編譯完成後,liquibase會在數據庫中創建兩張表:
databasechangelog
用於記錄執行的歷史腳本
databasechangeloglock
鎖定操作,防止多處同時執行
查看執行歷史:
SELECT * FROM databasechangelog;
字段說明:
id : 即changeset的id
filename: 數據變更文件的路徑
exectype: EXECUTED表示執行成功
md5sum : 每個changetset內容的md5值
注意: 執行過的changeset裏面的sql是不能修改的,liquibase會對比md5sum值,一旦發現md5值發生變化則會報錯。
比如說在一個changeset中create一張表,並且已經執行了,如果需要對該表增加字段,則只能在一個新的changeset中去ALTER這張表。