使用 LiquiBase 管理数据库变更 数据库版本管理

首先来了解下liquibase是什么

Liquibase是一个用于跟踪、管理和应用数据库变化的开源的数据库重构工具。它将所有数据库的变化(包括结构和数据)都保存在XML文件中,便于版本控制,代码有先进的管理工具git,为啥数据库就不能有呢?

liquibase 可以干嘛?

  • 不依赖于特定的数据库,目前支持包括Oracle/Sql Server/DB2/MySql/Sybase/PostgreSQL/Caché等12种数据库,这样在数据库的部署和升级环节可帮助应用系统支持多数据库。
  • 提供数据库比较功能,比较结果保存在XML中,基于该XML你可用Liquibase轻松部署或升级数据库。
  • 以XML存储数据库变化,其中以作者和ID唯一标识一个变化(ChangSet),支持数据库变化的合并,因此支持多开发人员同时工作。
  • 在数据库中保存数据库修改历史(DatabaseChangeHistory),在数据库升级时自动跳过已应用的变化(ChangSet)。
  • 提供变化应用的回滚功能,可按时间、数量或标签(tag)回滚已应用的变化。通过这种方式,开发人员可轻易的还原数据库在任何时间点的状态。
  • 可生成数据库修改文档(HTML格式)
  • 提供数据重构的独立的IDE和Eclipse插件。

传统的开发模式中的数据库修改之为什么使用liquibase

在日常的项目开发中,开发团队经常将数据库和应用程序视为单独的实体,这样就导致了数据库团队与应用开发团队分离造成团队之间信息交流不畅,信息交流不及时,这种情况通常表现为下面几种行为

  • 手工变更数据库
  • 不能与团队的其他成员分享数据库变更
  • 使用不一致的方法变更数据库或数据
  • 使用低效的手工方法管理数据库版本之间的变更

上面的几种行为都是我们在实际开发中遇到的问题,不仅效率低而且出错的机会也高,就算是老司机也会翻车

解决上面问题的思路是 减少人工手工变更数据库的机会,用程序管理数据库版本的更替

本文使用liquibase管理数据库的变更

使用liquibase 管理数据库的变更

使用步骤

  • step1: 创建一个数据库 变更日志(change log)文件。
  • step2: 在变更日志文件内部创建一个 变更集(change set)。
  • step3: 通过命令行或构建脚本对数据库运行变更集。
  • step4: 检验数据库中的变更。

step1:创建change log文件(changlog.xml)

change log 文件不一定要用xml写 还可以使用json sql

<?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"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

</databaseChangeLog>

step2: 添加变更集

<?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"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">

    <changeSet id="1" author="bob">
        <createTable tableName="department">
            <column name="id" type="int">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="active" type="boolean" defaultValueBoolean="true"/>
        </createTable>
    </changeSet>

</databaseChangeLog>

每个更改集都用“id”属性和“author”属性唯一标识。“作者”属性可以最大限度地减少重复的可能性。
liquibase将每个更改集视为要应用于数据库的原子更改。通常最好只在更改集中包含一个更改

step3: 运行ChangeSet
liquibase 可以使用命令行 Ant Maven Spring等工具运行
命令演示

liquibase --driver=com.mysql.jdbc.Driver \
     --classpath=/path/to/classes \
     --changeLogFile=com/example/db.changelog.xml \
     --url="jdbc:mysql://localhost/example" \
     --username=user \
     --password=asdf \
     update

step4: 检查你的数据库
你可以看到数据库现在包含一个名为“department”的表。还创建了另外两个表:“databasechangelog”和“databasechangeloglock”。
databasechangelog表包含已针对数据库运行的所有语句的列表。
databasechangeloglock表用于确保两台计算机不会同时尝试修改数据库。

在项目中使用liquibase

liquibase提供了对Spring的支持所以我们只需要引用对应的jar包并就行相关的配置就可以使用了

这里使用gradle作为示例
step1: 添加依赖

compile "org.liquibase:liquibase-core"
compile "com.github.sabomichal:liquibase-mssql"
compile "com.microsoft.sqlserver:mssql-jdbc"
testCompile "com.mattbertolini:liquibase-slf4j"

step2: 添加liquibase文件

在resource目录下创建liquibase文件夹,并创建master.xml文件作为主文件
使用 <include file="config/liquibase/changelog/xxx.xml" relativeToChangelogFile="false"/> 目录引入changelog文件

step3: 配置liquibase

@Bean
    public SpringLiquibase liquibase(DataSource dataSource, LiquibaseProperties liquibaseProperties) {

        SpringLiquibase liquibase = new SpringLiquibase(taskExecutor, env);
        liquibase.setDataSource(dataSource);
        //制定changelog的位置,这里使用的一个master文件引用其他文件的方式
        liquibase.setChangeLog("classpath:config/liquibase/master.xml");
        liquibase.setContexts(liquibaseProperties.getContexts());
        liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
        liquibase.setDropFirst(liquibaseProperties.isDropFirst());
        return liquibase;
    }

liquibase会在启动的时候更新数据库,可以配置为异步执行

对现有数据库应用重构

随着新特性添加到了应用程序中,经常需要变更数据库的结构或修改表约束。LiquiBase 提了超过 30 种数据库重构支持(参见 参考资料)。本节将介绍 4 种重构:添加列(Add Column)、删除列(Drop Column)、创建表(Create Table)和操作数据。

添加列

在项目的开始,几乎不可能考虑到数据库中的所有列。而有时候,用户要求新的特性 —例如为存储在系统中的信息收集更多的数据 —这就要求添加新的列。清单 4 使用 LiquiBase addColumn重构,向数据库中的 distributor表添加了一个列:

清单 4. 使用 LiquiBase 变更集中的 Add Column 数据库重构

<changeSet id="4" author="joe"> 
 <addColumn tableName="distributor"> 
   <column name="phonenumber" type="varchar(255)"/> 
 </addColumn> 
</changeSet>

删除列

假如在以后几个版本中,您想要删除在清单 4 添加的 phonenumber列。只需要调用 dropColumn重构,如清单 5 所示:

删除一个数据库列

<dropColumn tableName="distributor" columnName="phonenumber"/>

创建表

向数据库添加一个新表也是常见的数据库重构。清单 6 创建了一个新表 distributor,定义了列、约束和默认值:

清单 6. 在 LiquiBase 中创建一个新数据库表

<changeSet id="3" author="betsey"> 
 <createTable tableName="distributor"> 
   <column name="id" type="int"> 
     <constraints primaryKey="true" nullable="false"/> 
   </column> 
   <column name="name" type="varchar(255)"> 
     <constraints nullable="false"/> 
   </column> 
   <column name="address" type="varchar(255)"> 
     <constraints nullable="true"/> 
   </column> 
   <column name="active" type="boolean" defaultValue="1"/> 
 </createTable> 
</changeSet>

操作数据

在应用了结构性数据重构后(例如添加列和创建表),通常需要向受重构影响的表中插入数据。此外,可能需要修改查找表(或其他类型的表)中的现有数据。清单 7 展示了如何使用一个 LiquiBase 变更集插入数据:

清单 7. 使用一个 LiquiBase 变更集插入数据

<changeSet id="3" author="betsey"> 
 <code type="section" width="100%"> 
 <insert tableName="distributor"> 
   <column name="id" valueNumeric="3"/> 
   <column name="name" value="Manassas Beer Company"/> 
 </insert> 
 <insert tableName="distributor"> 
   <column name="id" valueNumeric="4"/> 
   <column name="name" value="Harrisonburg Beer Distributors"/> 
 </insert> 
</changeSet>

您应该编写用于操作数据的 SQL 脚本,因为使用 LiquiBase XML 变更集限制很多。有时候使用 SQL 脚本向数据库应用大量的变更会简单一些。LiquiBase 也可以支持这些情景。清单 8 调用变更集中的 insert-distributor-data.sql来插入 distributor表数据:

清单 8. 从 LiquiBase 变更集运行一个定制 SQL 文件

<changeSet id="6" author="joe"> 
 <sqlFile path="insert-distributor-data.sql"/> 
</changeSet>

LiquiBase 支持很多其他数据库重构,包括 Add Lookup Table 和 Merge Columns。可以使用如清单 4 到清单 8 所示的方式定义所有这些支持。

与gradle整合

安装gradle插件

gradle 2.0 以上写法

plugins {
  id 'org.liquibase.gradle' version '2.0.0'
}

gradle 2.0 以下写法

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath "org.liquibase:liquibase-gradle-plugin:2.0.0"
    }
}
apply plugin: 'org.liquibase.gradle'

设置classpath路径

configurations {
    liquibaseRuntime
}

dependencies {
  // 选择你需要的依赖
  liquibaseRuntime 'org.liquibase:liquibase-core:3.6.1'
  liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.0'
  liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'
}

配置 liquibase activities(类似与profile)

liquibase {
    activities {
        prod {
            changeLogFile ''
            url ''
            username ''
            password ''
        }
        dev {
            changeLogFile "config/liquibase/master.xml"
            url 'jdbc:h2:mem:inspection;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
            username 'inspection'
            driver ''
            password ''
        }
        runList = 'dev' // 这里代表选择哪一个配置 可用参数代替
    }

}

入口类配置

默认入口类
liquibase.integration.commandline.Main

配置方法

liquibase {
  mainClassName = 'liquibase.ext.commandline.LiquibaseAlternativeMain'
}

配置完成后就可以在gradle中看到liquibase的task

注意:如果使用了include等标签需要注意 file="xxx/xxx/xxx.xml" 绝对路径和相对路径,如果设置relativeToChangelogFile=“false” 这说明你使用的是绝对路径,true 选择的是相对路径

更多信息可以来blog+bbs www.youngboy.vip 逛逛

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章