Liquibase in practice
1. 概述
这是一篇简略的使用指南,我们使用Liquibase来持续开发演进java应用程序的数据库的结构。我首先来看下java应用是怎么整合使用Liquibase,接着是来看关于Spring,Hibernate与Liquibase的整合。
总的来说,Liquibase的核心是changeLog文件-一个xml文件,用来跟踪管理数据库的演化过程。
首先,我们需要把liquibase-core加入到pom.xml文件
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.4.1</version>
</dependency>
更新的版本,请点这里查看
更多关于Liquibase的功能简介
2. Change Log文件
我们先看个简单的 changeLog 文件–这个 changeLog文件只是简单在在table user里新增一个字段address
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
<changeSet author="John" id="someUniqueId">
<addColumn tableName="users">
<column name="address" type="varchar(255)" />
</addColumn>
</changeSet>
</databaseChangeLog>
注意思考liquibase是怎么通过
id和author来惟一识别一个change set–识别change set是为了确保每一个change set只能被执行一次,否则,执行多次会报错或破坏db的结构。
让我们看下怎么把上面的change log加入到我们的应用里并确保它在应用起动时被执行
3. 使用Spring Bean配置并运行Liquibase
第一次执行方法,配置一个Spring Bean在Spring Boot应用启动时执行change log。当然还有其他方法,但是如果我们使用Spring开发我们的应用时,这是一种简单实用的方法。
@Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setChangeLog("classpath:liquibase-changeLog.xml");
liquibase.setDataSource(dataSource());
return liquibase;
}
注意:我们引用的
change log文件liquibase-changeLog.xml要在运行前被加入到我们的class path里。
4. Spring Boot整合并运行Liquibase
如果你正在使用Spring Boot作为开发框架,只需要简单的配置,甚至不需要为Liquibase定义一个Bean
你只需要把你所有的change log文件都包含在这个文件内src/resources/db/changelog/db.changelog-master.yaml,那么在Spring Boot启动时,这些change log就行被应用到db。
- 首先你需要把
liquibase-code依赖加入到你的pom.xml文件里 - 你可以通过
liquibase.change-log这个Spring Boot配置项来修改默认的change log文件,如下:liquibase.change-log=classpath:liquibase-changeLog.xml
5. 使用Maven plugin来生成change log文件
我们可以使用Liquibase Maven plugin来生成chnage log,替代手动编写change log,节省不少时间。
5.1 配置插件
在pom.xml里加入如下Liquibase配置
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
</dependency>
...
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
</plugin>
</plugins>
5.2 从已经存在的数据库结构里生成change log
配置好上面的插件后,用liquibase-mavin-plugin的generateChangeLog这个goal从已经存在的数据库结构生成chnage log
mvn liquibase:generateChangeLog
在运行上面的maven命令之前,首先需要在liquibase.properties配置文件里加入以下配置
url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
outputChangeLogFile=src/main/resources/liquibase-outputChangeLog.xml
最终产生的changeLog文件,可以用来作为另一个数据库的初始化脚本,或者用来导入数据到另一个相同结构的数据库。生成的chnagelog文件看起来应该像下面这段xml代码。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog ...>
<changeSet author="John (generated)" id="1439225004329-1">
<createTable tableName="APP_USER">
<column autoIncrement="true" name="id" type="BIGINT">
<constraints primaryKey="true"/>
</column>
<column name="accessToken" type="VARCHAR(255)"/>
<column name="needCaptcha" type="BIT(1)">
<constraints nullable="false"/>
</column>
<column name="password" type="VARCHAR(255)"/>
<column name="refreshToken" type="VARCHAR(255)"/>
<column name="tokenExpiration" type="datetime"/>
<column name="username" type="VARCHAR(255)">
<constraints nullable="false"/>
</column>
<column name="preference_id" type="BIGINT"/>
<column name="address" type="VARCHAR(255)"/>
</createTable>
</changeSet>
...
</databaseChangeLog>
5.3 生成一chnage log文件,显示两个数据库之间存在的差异
如果我们现在手头上有两个版本数据库结构,但是,由于数据库开发演化过程中没有同步好,我们现在不清楚两个数据库版本之间存在哪些差异。我们可以使用这个插件,生成一个chnage log文件,包括了两个已经存数据库版本之间有哪些差异(比如,最常见的就是一个是开发时用的数据库,一个是正在生产使用的版本)。
mvn liquibase:diff
下面是liquibase.properties文件的配置
changeLogFile=src/main/resources/liquibase-changeLog.xml
url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
referenceUrl=jdbc:h2:mem:oauth_reddit
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml
referenceDriver=org.h2.Driver
referenceUsername=sa
referencePassword=
生成出来的change log文件应该跟下面的代码片段相似。
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog ...>
<changeSet author="John" id="1439227853089-1">
<dropColumn columnName="address" tableName="APP_USER"/>
</changeSet>
</databaseChangeLog>
这是一个十分有用的方法,在持续开发演化你的数据库结构–比如:让hibernate自动生成一个数据库结构脚本用来搭建开发环境,然后用这个来作来针对旧数据库结构的参考
6. 使用Liquibase Hibernate 插件
如果你的应用使用了Hibernate-接下来,我们来看下一个非常有用的生成change log的方法。
首先-下面是liquibase-hibernate plugin在maven里的配置
6.1 插件配置
首先,让我们看来最新版本的插件配置,还有需要用到的依赖
<plugins>
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<configuration>
<propertyFile>src/main/resources/liquibase.properties</propertyFile>
</configuration>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate4</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>1.7.3.RELEASE</version>
</dependency>
</dependencies>
</plugin>
</plugins>
6.2 对比数据库与Jpa Entities之间的差异,且生成差异的change log
这个插件很有趣,我们可以用这个插件对比已经存在的数据库(例如生产数据库)和最新的java persistence entities对象之间的差异,并生成差异部分的changeLog
简单的举个例子–一旦你改了某个entity,你可以简单容易地生成一个反映这次修改的change log文件,通过对比旧的数据库结构,这是一个简结,实用的方法用来演化你的数据库结构,
在liquibase 的配置文件里加入以下配置
changeLogFile=classpath:liquibase-changeLog.xml
url=jdbc:mysql://localhost:3306/oauth_reddit
username=tutorialuser
password=tutorialmy5ql
driver=com.mysql.jdbc.Driver
referenceUrl=hibernate:spring:org.baeldung.persistence.model?dialect=org.hibernate.dialect.MySQLDialect
diffChangeLogFile=src/main/resources/liquibase-diff-changeLog.xml
注意:referenceUrl用来扫描包下面的类,所以dialect参数是是必须的。
7. 结论
在这篇指导文章里,我们介绍说明了几种使用Liquibase的方法,这些方法是安全成熟可靠的,用来演化,重构数据库结构
文单的代码可以在原作者的github里找到,这是一个基于Eclipse的项目,所以很容易导入Eclipse并运行。