使用 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 逛逛

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