What’s Liquibase?
Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制。
Liquibase具备如下特性:
* 不依赖于特定的数据库,目前支持包括Oracle/Sql Server/DB2/MySql/Sybase/PostgreSQL/Caché等12种数据库,这样在数据库的部署和升级环节可帮助应用系统支持多数据库。
* 提供数据库比较功能,比较结果保存在XML中,基于该XML你可用Liquibase轻松部署或升级数据库。
* 以XML存储数据库变化,其中以作者和ID唯一标识一个变化(ChangSet),支持数据库变化的合并,因此支持多开发人员同时工作。
* 在数据库中保存数据库修改历史(DatabaseChangeHistory),在数据库升级时自动跳过已应用的变化(ChangSet)。
* 提供变化应用的回滚功能,可按时间、数量或标签(tag)回滚已应用的变化。通过这种方式,开发人员可轻易的还原数据库在任何时间点的状态。
* 可生成数据库修改文档(HTML格式)
* 提供数据重构的独立的IDE和Eclipse插件
Integrate Liquibase with Ant
你所需要的Liquibase环境,其实只是一个Jar包而已。 通过Ant加载该Jar包,就可以集成Liquibase实现数据版本控制
Liquibasse支持原生SQL,但是推荐使用Liquibase的Changeset语法,因为ChangeSet语法是跨数据库的,你几乎不会有数据库迁移的麻烦,这也是Liquibase受到追捧的原因之一。
怎么构建一个HelloWorld表
<?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-2.0.xsd http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd"> <changeSet id="1.0.0" author="ryan" > <createTable tableName="helloworld"> <column name="ID" type="VARCHAR2(40)"> <constraints primaryKey="true" nullable="false"/> </column> <column name="KEY" type="VARCHAR2(200)"/> <column name="DISPLAYNAME" type="VARCHAR2(200)" /> <column name="DEFAULT_MESSAGE" type="CLOB" /> </createTable> <rollback> drop table helloworld; </rollback> </changeSet> </databaseChangeLog>
上面的XML 文件定义了创建Helloworld表的语句,同时ChangeSetID为1.0.0 。 这个ID是相当重要,ID会作为Version控制的唯一标识,如果你要回滚操作,就可以根据相应的ID进行回滚。
引入Liquibase Jar包
<path id="classpath-liquibase"> <fileset dir="${global.dir}/../lib/"> <include name="liquibase.jar" /> <include name="ojdbc14.jar" /> </fileset> </path>
更新数据表:
<ant target="update-Database-handler"> <property name="update.changeSet.file" value="${changeSet.file}" /> <property name="update-database-schema" value="schemaA" /> <property name="database.username" value="${jdbc.user}" /> <property name="database.password" value="${jdbc.password}" /> <property name="databaseChangeLogTableName" value="${databaseChangeLogTableName}" /> <property name="databaseChangeLogLockTableName" value="${databaseChangeLogLockTableName}" /> </ant>
此段ANT语句定义了Update操作,你需要通过Propertis传入相应的ChangeSet文件路径以及数据库相应的用户名密码。
databaseChangelogTablename 代表日志表,
databaseChangeLogLockTableName代表锁状态表。
Tag Table :
<ant target="tag-handler"> <property name="database.username" value="${jdbc.user}" /> <property name="database.password" value="${jdbc.password}" /> <property name="tag.id" value="${tag.id}" /> <property name="databaseChangeLogTableName" value="${databaseChangeLogTableName}" /> <property name="databaseChangeLogLockTableName" value="${databaseChangeLogLockTableName}" /> </ant>
当你更新了多个ChangeSet文件并测试稳定过后,你需要将当前的变更打上一个Tag,也就是一个新的版本,而这个Tag Id 最好与最新的ChangeSet ID 保持一致,一定要注意,Liquibase只支持基于TagID的回滚,所以当版本稳定过后一定要打上Tag。
Rollback Database:
<target name="rollback-Database-handler"> <echo message="Roll Back Database incording the file of ${rollback.changeSet.file}" /> <echo>url="${jdbc.url}"</echo> <echo>username="${database.username}"</echo> <echo>password="${database.password}"</echo> <echo>rollbackTag="${rollback.tag.id}"</echo> <taskdef resource="liquibasetasks.properties"> <classpath refid="classpath-liquibase" /> </taskdef> <if name="liquibase.mode" value="output"> <property name="outputProperties" value="${sql.file.output.dir}/${rollback-database-schema}.${outputSql.suffix}" /> <rollbackDatabase changeLogFile="${rollback.changeSet.file}" url="${jdbc.url}" username="${database.username}" password="${database.password}" classpathref="classpath-liquibase" rollbackTag="${rollback.tag.id}" databaseChangeLogTableName="${databaseChangeLogTableName}" databaseChangeLogLockTableName="${databaseChangeLogLockTableName}" outputFile="${outputProperties}"> </rollbackDatabase> <else> <rollbackDatabase changeLogFile="${rollback.changeSet.file}" url="${jdbc.url}" username="${database.username}" password="${database.password}" classpathref="classpath-liquibase" rollbackTag="${rollback.tag.id}" databaseChangeLogTableName="${databaseChangeLogTableName}" databaseChangeLogLockTableName="${databaseChangeLogLockTableName}"> </rollbackDatabase> </else> </if> </target> 上面的代码就是基于TagId的回滚。Liquibase对于Update和Roll Back操作支持Output模式,也就是不会对数据库进行操作,只是将ChangeSet的语法转义为相应的SQL语句并输出,这样的话你可以在本地更方便的进行分离测试。