说明
项目升级时,数据库的变更手动维护很麻烦,而且容易出错,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这张表。