數據庫版本管理工具之flyway

1.引言  

       隨着項目不斷的增大,尤爲是一個在不斷開發完善的項目,隨着需求變化,數據庫的schema也會跟着變化,數據庫也須要不斷的擴充,加表加字段,(每一次的增長稱做一次DB的遷移migration)你是否還在用着最原始的方式, 用文件管理每次的SQL升級腳本,加了哪些字段,加了那些表,如今能夠用數據庫版本控制工具垂手可得搞定了。html

       flyway支持java API的操做方式,能夠和spring 框架進行無縫鏈接,使其在系統啓動的時候檢查並升級數據庫的版本(特別適合於java項目)。java

2.flyway的特色

2.1使用它以前先要了解一些概念:

  • 版本:對數據庫的每一次變動可稱爲一個版本。spring

  • 遷移:Flyway把數據庫結構從一個版本更新到另外一個版本叫作遷移。sql

  • 可用的遷移:Flyway的文件系統識別出來的遷移版本。數據庫

  • 已經應用的遷移:Flyway已經對數據庫執行過的遷移。tomcat

2.2 .flyway最基本的幾個命令。

  • Migrate:應用全部的遷移到最新版本,它會在你的DB中新建個表schema_version來存放每次升級的版本信息。mvc

  • Clean:clean all objects框架

  • Info:打印全部的遷移的信息以及狀態。ssh

  • Validate:遷移以前進行驗證。maven

  • Baseline:初始化schema_version表,並插入一條原始verion=1。

  • Repair:它主要作了兩件事,移除全部失敗的遷移(升級),重置校驗和。

2.3.既支持sql方式升級也支持java方式升級

      1)支持SQL(還有PL/SQL,T-SQL)文件的方式進行升級(這就是最原始的方式,可是得按照必定的規則規則,例如:V2_0_0_0__update.sql,  V2_0_0_1__update.sql。

sql腳本的命名規則:

  • prefix: default: V (大寫哦) 

  • version: 版本號,也可使用大小版本組合的方式,小版本號用單 _區分  

  • separator: 分隔符,雙下劃線 __  

  • description: 描述(你懂得,必需要有意義)  

  • suffix: 後綴 default:  .sql

      2)固然也支持Java方式,繼承 JdbcMigration便可,例如我定義了一個升級的類:public class V1_2__Another_user implements JdbcMigration {} 若是你使用JVM平臺,建議你用Java API,也支持Android哦。

2.4 可使用命令行客戶端Command-line client來執行命令來升級數據庫的版本。

   這兒就不詳細介紹了。這個不是重點。重點在介紹java的使用

2.5  固然flyway也提供了插件支持.

        有以下插件支持:Maven, Gradle,SBT和Ant,還有更多Plugins,提供對Spring Boot, Dropwizard, Grails, Play, Griffon, Grunt, Ninja 的支持。 其中能夠研究下flyway-test-extensions,有Usage flyway dbunit test、Usage-flyway-spring-test 功能很強大。

3. 在maven項目裏面的spring mvc裏面使用flyway在系統啓動的時候去檢查並升級數據庫的版本。

3.1引入flyway的jar包,在pom.xml裏面內容以下:

<properties>
    <flyway.version>2.3</flyway.version>
</properties>

<!--flyway要用到的jar包  -->
<dependency>
    <groupId>com.googlecode.flyway</groupId>
    <artifactId>flyway-core</artifactId>
    <version>${flyway.version}</version>
    <exclusions>
        <exclusion>
            <artifactId>commons-logging</artifactId>
            <groupId>commons-logging</groupId>
        </exclusion>
    </exclusions>
</dependency>

3.2編寫數據庫的版本的腳本文件,放到/src/main/resources的flyway裏面:

(flyway找腳本的時候默認去/src/mian/resources下面的db/migration,若是要放在別的位置,後面的地方要配置一下

3.3. 定義在應用啓動時自動運行Flyway 的Java 類,並實現其邏輯代碼

public class DatabaseFlywayMigration {
 private DataSource dataSource;  
  
    public void setDataSource(DataSource dataSource) {  
        this.dataSource = dataSource;  
    }  
    
    public void migrate() {  
        Flyway flyway = new Flyway();  
        flyway.setDataSource(dataSource);
        flyway.setLocations("flyway"); // 設置flyway掃描sql升級腳本、java升級腳本的目錄路徑或包路徑(表示是src/main/resources/flyway下面,前綴默認爲src/main/resources,由於這個路徑默認在classpath下面)
        flyway.setEncoding("UTF-8");   // 設置sql腳本文件的編碼
        flyway.setOutOfOrder(true);
        //flyway.setDataSource(dataSource);  
  
        //flyway.setSchemas("flywaydemo"); // 設置接受flyway進行版本管理的多個數據庫  
        // flyway.setTable("schema_version"); // 設置存放flyway metadata數據的表名  
        //flyway.setValidationMode(ValidationMode.ALL); // 設置執行migrate操做以前的validation行爲  
        //flyway.setValidationErrorMode(ValidationErrorMode.FAIL); // 設置當validation失敗時的系統行爲  
          
        // 設置當validation失敗時的系統行爲
	try {
	    flyway.setInitOnMigrate(true);
	    flyway.migrate();
	 } catch (FlywayException e) {
	    flyway.repair();
	    e.printStackTrace();
	 }
    }  
}

3.4 設置在系統啓動是自動運行DatabaseFlywayMigration類的migrate方法

在ApplicationContext.xml(spring mvc的上下文中加入以下:)

<!-- flayway -->
<bean id="flywayMigration1" class="com.kedacom.flyway.DatabaseFlywayMigration" init-method="migrate">
    <property name="dataSource" ref="dataSource" />
</bean>

從上面的bean 定義中咱們能夠看到,咱們爲flywayMigration 這個bean 實例注入了一個數據源,Flyway 的全部操做將針對這個數據源進行;同時咱們經過init-method 屬性指定了Spring 在實例化該bean 之後,主動執行該bean 的migrate 方法,而該方法內會執行Flyway 更新數據庫的操做。

至此,咱們達到了在應用啓動時,Spring 實例化上下文的時候,在Spring 實例化flywayMigration 這個bean 的時候,自動執行Flyway 更新數據庫的操做。

可是,咱們尚未達到目的,萬一Flyway 還在更新數據庫,沒有完成更新操做以前,應用程序的其餘邏輯已經開始使用數據庫進行其餘操做了,會致使應用程序產生不少bug ,甚至根本運行不起來。

要解決這個問題,咱們能夠利用Spring 的bean 依賴原理,讓關鍵的數據庫操做bean 依賴於flywayMigration 這個bean ,達到在flywayMigration 沒有實例化完成(數據庫更新操做完成)以前,不能進行任何其餘數據庫相關操做。

利用Spring 的bean 依賴讓flywayMigration 優先處理數據庫更新操做:

<!-- 將鏈接池注入到 JdbcTemplate對象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" depends-on="flywayMigration1">
    <property name="dataSource" ref="dataSource"></property>
</bean>

至此,運行就能夠了。

可是值得注意的是:

 在啓動的tomcat的時候,內容以下:


可是在schema_version裏面已經執行過的版本號以下:

其實並無執行個人v1_0_0_0__update.sql這個腳本,

DROP TABLE if EXISTS env;
-- 環境 方案 
CREATE TABLE env(
    id varchar(36) not null,
    env_name varchar(50) not null,
    env_username varchar(30) comment '環境用戶名',
    env_password varchar(30) comment '環境用戶密碼',
    ssh_port int default 22,
    state varchar(30) ,
    primary key(id)
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

由於沒有建立這個數據庫表

反而是第二個版本的sql腳本給執行了  v1_0_0_1__update.sql

緣由是schema_version表的version爲1其實被flyway默認爲v1_0_0_0版本了,因此沒有執行,而version版本爲表示初始化schema_version。因此咱們能夠改成從v2_0_0_0__update.sql開始第一個sql版本。這樣就會執行了,反正flyway2.3版本是這樣的,不知道後面的版本有沒有改善這個問題。

相關文章
相關標籤/搜索