几年来,我一直在使用标语“Liquibase:数据库的源代码控制”,尽管事实上开发人员总是在寻找分类错误并且喜欢争辩说它不是 真正的 源代码控制系统,因为 bleah,惨死,惨死。
尽管如此,尽管存在差异,但我一直认为这是一个很好的类比。事实上,虽然 Liquibase 的早期版本使用术语“迁移”作为应用未运行更改的命令,但我在 1.0 早期将命令更改为“更新”以更好地匹配最新状态的术语艺术(当时)版本控制,颠覆。
那么,为什么不为您的数据库使用 SVN 或 Git 或任何其他“真正的”版本控制系统呢?因为管理代码的方式与管理数据库的方式有着根本的区别——代码文本如何从 A 点到 B 点并不重要,但是如果数据库中的数据从 A 点到 B 点采用错误的路径B点它可能会产生可燃的后果。因此,Liquibase 擅长的是让您指定这些步骤并确保它们根据需要针对您的所有数据库执行。这些更改以基于文本的人类可读格式存储,以便您可以在您拥有的任何“真实”版本控制系统中管理它们。
那么对于像 Git 这样的版本控制系统来说,通常的 Liquibase 工作流程是怎样的呢?
开始一个新项目:“创建一个空的变更日志文件”又名“git init”
如果您正在创建一个新的 Git 管理的目录,您将运行“git init”来初始设置存储库。没有特殊的 Liquibase 命令来创建新的数据库变更日志,您只需创建一个空的 XML(如果您愿意,也可以创建 YAML 或 JSON)文件。
开始编码:“add changeSets”又名“git add”
当您创建新的源文件时,“git add”会将这些文件添加到索引中,以便它们将包含在您的下一次提交中。在 Liquibase 中,您将新的变更集添加到 databaseChangeLog 文件中,该文件描述了您需要按执行顺序完成的步骤。
<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.4.xsd">
<changeSet id="SAMPLE_1" author="alice">
<createTable tableName="employee">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="first_name" type="varchar(255)"/>
<column name="last_name" type="varchar(255)">
<constraints nullable="false"/>
</column>
</createTable>
</changeSet>
<changeSet id="create address table" author="bob">
<createTable tableName="address">
<column name="id" type="int" autoIncrement="true">
<constraints primaryKey="true"/>
</column>
<column name="line1" type="varchar(255)">
<constraints nullable="false"/>
</column>
<column name="line2" type="varchar(255)"/>
<column name="city" type="varchar(100)">
<constraints nullable="false"/>
</column>
<column name="employee_id" type="int">
<constraints nullable="false" foreignKeyName="fk_address_employee" references="employee(id)"/>
</column>
</createTable>
</changeSet>
</databaseChangeLog>
保存你所做的工作:“liquibase update”又名“git commit”
使用 Git,当您处于一个好的停止点时,“git commit”会将您的更改保存到本地存储库。 “Liquibase 更新”会将您的新变更集应用到您的本地数据库。 Once 可能会争辩说“liquibase update”更适合编译你的代码,因为这是你在添加每个 changeSet 之后应该做的事情,以确保你的逻辑是正确的。尽管如此,运行“liquibase update”将依次查看每个 changeSet 并检查数据库的 DATABASECHANGELOG 表以确定它是否已运行,并且只会运行新的 changeSet。
与团队其他成员分享你的工作:“git add;提交; git push”又名“git push”
一旦您测试了您的代码和/或数据库更改在本地工作,就可以将您的更改发送给团队的其他成员了。使用标准 Git,您已经添加并提交了您的代码,因此您只需推送您的提交即可。然而,到目前为止,使用 Liquibase 时,您只是在编辑一个文件,因此您需要在“git push”之前对文件执行标准的“git add”和“git commit”-将其与代码库的其余部分一起使用。
@#%$&ing 冲突:“git merge”又名“merge hell”
就像代码一样,您会遇到代码冲突。这就是让变更日志文件成为人类可读文本格式的价值所在。 Git 和其他版本控制系统通常可以无缝合并您的更改,但如果不能,您的标准合并工具将为您提供合并更改的机会。
通常更改日志冲突可以简单地通过确保包含所有更改集及其所有更改集来解决,因为您已经划分了工作并且都在数据库的不同区域工作。但是,有时您都尝试添加同一个表或都将现有列的数据类型更改为不同的类型。在这些情况下,您可以选择最有意义的变更集来保留和/或创建新的变更集来组合有问题的变更集。根据数据库中冲突的广泛程度,您可能希望使用 liquibase 前提条件或上下文来控制执行合并变更集的位置。
分支:“git分支; git 合并”与“git 分支; git 合并”
开发从来都不是直截了当的,这就是分支机构如此宝贵的原因。这适用于您的数据库,也适用于您的代码。 Liquibase 旨在通过结合 id、作者和文件名单独跟踪每个 changeSet 来处理分支。早期的数据库版本控制系统只会使用递增的版本号或时间戳,当多个分支都尝试添加版本“42”时,这会遇到问题。
使用 Liquibase,您将失去漂亮的版本号,而只知道 changeSets“nvoxland:3113:com/example/changelog.xml”、“nvoxland:421:com/example/changelog.xml”和“fred:421:com/ example/changelog.xml”被执行。可以把它想象成 Git 如何不得不放弃简单的 SVN 版本编号以支持像“95ccad016ede5ded704203e632b59cc1417957c2”这样的版本来处理分布式分支。
当您需要创建分支时,只需像其他所有内容一样在您的版本控制中对变更日志文件进行分支。当您在分支中追加更改时,这些更改将仅应用于您的本地数据库。当您将变更日志文件合并回基本分支时,这些新的变更集在变更日志文件中的位置可能会高于已经应用于其他数据库的其他变更集,但这没关系,因为每个变更集都被单独检查并且新合并的变更集仍然会以正确的顺序应用于所有数据库。