Liquibase简介íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi Liquibase具备如下特性:
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 不依赖于特定的数据库,目前支持包括Oracle/Sql Server/DB2/MySql/Sybase/PostgreSQL/Caché等12种数据库,这样在数据库的部署和升级环节可帮助应用系统支持多数据库。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 提供数据库比较功能,比较结果保存在XML中,基于该XML你可用Liquibase轻松部署或升级数据库。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 以XML存储数据库变化,其中以作者和ID唯一标识一个变化(ChangSet),支持数据库变化的合并,因此支持多开发人员同时工作。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 在数据库中保存数据库修改历史(DatabaseChangeHistory),在数据库升级时自动跳过已应用的变化(ChangSet)。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 提供变化应用的回滚功能,可按时间、数量或标签(tag)回滚已应用的变化。通过这种方式,开发人员可轻易的还原数据库在任何时间点的状态。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 可生成数据库修改文档(HTML格式)
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 提供数据重构的独立的IDE和Eclipse插件
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi Liquibase的核心就是存储变化的XML,如例:
<?xml version="1.0" encoding="UTF-8"?> íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<databaseChangeLogíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<changeSet id="1" author="bob">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<createTable tableName="department">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<column name="id" type="int">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<constraints primaryKey="true" nullable="false"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</column>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<column name="name" type="varchar(50)">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<constraints nullable="false"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</column>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<column name="active" type="boolean" defaultValue="1"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</createTable>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</changeSet> íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</databaseChangeLog>
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
其中,changeSet包含不同的数据库变化,
几乎涵盖了所有的数据库变化类型,具体支持的类型要看API,我这里给几个例子:
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 创建和删除表、视图、存储过程、主键、外键、索引等
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 重命名表、视图、列等
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 加入列缺省值、唯一约束、非空约束等
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 合并两个列
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 在一个表的数据的基础上创建一个字典表
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 除此之外,Liquibase还允许你运行自己的Sql脚本、执行Shell程序。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 之所以所说”几乎涵盖“,是因为目前我发现不支持用户自定义数据和自定义函数的。由于在我新的数据库开发原则中摒弃了对他们的依赖,所以也不痛苦。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiLiquibase在持续集成中的应用
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 如果你基于Java开发,你可能会更喜欢Liquibase,如果基于Ruby On Rails开发,你可能会选择Migration 和 Rake。我基于.Net,考察过Red Gate($),Migration.Net,
Machine.Migrations,Power Tools等等,最终还是选择了Liquibase。如何整合到我的开发流程中来,我选择命令行以及基于命令行的MsBuild任务。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 用命令行搞一个bat文件执行Liquibase,用户数据库部署(见我例子中的deploy.bat)。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi Msbuild提供比较、部署、文档生成等等全套功能,用于开发的全过程,当然也用于CC.Net(见例子中的ci.proj)。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 具体的应用包括:
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 开发人员在本地完成一个阶段的开发后,使用ci.proj中的diff target比较本地数据和基线数据,产生changelog.xml,提交到SVN(这里,XML文件中的changeSet中的Author取开发人员本地机器的用户名)
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * CC.Net检测到SVN的变化,触发持续集成过程,调用ci.proj中的deploy在一个测试数据库中创建最新的数据结构,然后对实体类和访问层进行测试(开发人员在本地机器的测试亦如此)。测试成功,使用ci.proj中的doc生成文档,发布在持续集成服务器的IIS中。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 如果是trunk项目则在测试完成后需要在SVN上打Tag,然后使用ci.proj中的publish发布数据库部署升级程序(含changelog.xml)
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 发布的数据库部署升级程序中含deploy.bat给部署人员用以部署或升级现有的产品系统数据库。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 关于changelog.xml的合并:
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 每一次开发人员有新的changelog.xml提交,我会通过SVN的Merge功能将其新的changeSet合并
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 这个过程可以通过SVN自动完成,但鉴于数据库的变化影响面太大,需要谨慎审核,因此还是选择手工来做
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 关于
test.proj: 这是用MsBuild写的一个测试案例,测试ci.proj提供的数据库比较和升级功能。 íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰiíS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 关于ci.proj的说明:
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi * 对
dtproperties的特殊处理
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi 一旦你使用过Sql Server的
企业管理器操作过数据库,会自动生成这个表存一些数据库对象的属性。虽然在
企业管理器中显示为系统表,但它的object_id很大,使得liquibase将其看做用户表,会影响数据库比较结果,因此在ci.proj中会检查参与比较的两个数据是否存在该表,如果不存在则创建它。
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi *
<Target Name="CheckExec">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
MsBuild使用Java命令行调用liquibase,如果执行出错,MsBuild不能得到该错误,这样将导致CC.Net的持续集成在失败时报成功。没有找到更好的办法,我将执行Java得到的输出写入exec.log文件,然后用CheckExec检查其中是否有Failed关键字。可能还有其他的关键字需要检查,如果园友发现还请告诉我。íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Target Name="CheckExec">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<ReadLinesFromFile File="$(ExecLog)">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Output TaskParameter="Lines" PropertyName="ExecOutput"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</ReadLinesFromFile>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Message Text="$(ExecOutput)" Importance="high"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<StringComparison Comparison="Contains" Param1="$(ExecOutput)" Param2="Failed">íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Output TaskParameter="Result" PropertyName="StringSearchResult"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</StringComparison>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Delete Files="$(ExecLog)"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
<Error Text="liquibase report error" Condition="$(StringSearchResult)"/>íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi
</Target>
íS
¾
£Hª;www.netcsharp.cnÅÑà×AŰi附件:
db-ci-deploy.zip