Java敏捷数据库迁移框架——Flyway

1.引言

想到要管理数据库的版本,是在实际产品中遇到问题后想到的一种解决方案,当时各个环境的数据库乱作一团,没有任何一个人(开发、测试、维护人员)能够讲清楚当前环境下的数据库是哪个版本,与哪个版本的应用相匹配,如何升级到与新版本的应用相匹配。

想到管理数据库版本时,先是心底形成了一个初步的解决方案,大致是通过数据库中的某张表来记录数据库表结构的历次更新与对应版本,在每次数据库表结构调整时除了提供库表更新sql ,还必须提供更新记录与对应版本的sql,以帮助维护数据库版本信息,并在遇到问题时提供相关的排查依据。

后来据此思路在网络上搜索了一把,结果搜到Liquibase (另一款开源数据库版本管理工具)。在学习了解Liquibase 的时候,经高手介绍又了解到了Flyway 这个项目的存在。经过一番了解,最后我们选择了Flyway ,主要原因是Flyway 支持sql 脚本,而Liquibase 只支持XML 方式的数据库表结构定义,虽然在新的版本中号称在XML的数据库表结构定义方式中支持了sql 脚本。

虽然Flyway 的中文文档近乎为零,英文文档也凤毛麟角,但它却是我们最理想的数据库版本管理工具,它不但支持sql 脚本,还支持Java 代码直接操作数据库(在版本升级时做数据迁移相当有用),有Maven 插件,支持命令行(我们的平台数据库有部分由C 语言项目管理),而且在Spring 框架的配合下,很容易就能实现应用启动时自动检查并升级数据库的功能。

2.什么是flyway

Flyway 是独立于数据库的应用、管理并跟踪数据库变更的数据库版本管理工具。

Flyway 的项目主页是 http://flywaydb.org/ )(最近才迁移到这个主页,之前一直在googlecode 下管理http://code.google.com/p/flyway/ ),在项目的主页上可以看到Flyway 与几款主流数据库版本管理工具的特性对比列表。

3.为什么使用flyway

我们遇到的问题(以下内容来自Flyway 的一些英文文档,从中抽取出来的我们也遇到的一些主要问题):

  • 不同的开发人员在开发产品特性时,都有可能更新数据库(添加新表,新的约束等)。当开发人员完成工作并提交代码时,代码会被合并到主分支并在测试服务器上执行单元测试与集成测试。我们在哪个环节来执行数据库的更新操作呢?由QA 部门手工执行sql 脚本?或者我们开发一断程序自动执行数据库更新?以什么顺序来执行这些更新脚本?这些问题同样存在于生产环境。

  • 我们的产品部署在不同的客户服务器上,以及很多的测试、联调、实验局、销售环境上。不同的客户和测试环境上都部署着不同版本的产品。当他们需要升级他们的产品到新的版本时,我们不仅需要让他们的管理员可以升级产品到新的版本,同时需要保留他们的已有数据。在升级产品的步骤中,我们清楚地知道客户数据库的当前版本,以及需要在该数据库上执行哪些数据库更新脚本,来更新数据库表结构与数据库中已存在的数据。当升级完成时,数据库表结构及数据应当与升级后的产品版本保持一致。
  • 有的时候,我们需要通过代码(Java )来维护一些已存在的数据,如通过代码来维护blob 类型的用户头像数据。
  • 当升级失败时(比如在升级过程中出现网络连接失败),我们应当支持对失败进行修复。

4.如何使用flyway

Flyway 的主要任务是管理数据库的版本更新,在Flyway 中称每次数据库更新为一个migration ,为了更顺口,我们下面称之为数据库脚本。Flyway 支持SQL-based migrations 和Java-based migrations 。

Flyway 支持的数据库脚本有sql 脚本与java 代码,sql 脚本即普通的sql 脚本,包含创建数据库、表,更新库表结构,数据插入、更新、删除等sql 语句,java 代码则是通过一个有效的数据源,使用java 语言来进行数据库的操作,这里针对的读者是对数据库操作有一定熟悉程度的群体,不再详细讲解如何编写数据库脚本。

  • SQL 脚本文件默认位置是项目的源文件夹下的db/migration  目录。
  • Java 代码默认位于db.migration  包。
  • SQL 脚本文件及Java 代码类名必须遵循以下命名规则:V<version>[_<SEQ>][__description] 。版本号的数字间以小数点(. )或下划线(_ )分隔开,版本号与描述间以连续的两个下划线(__ )分隔开。如V1_1_0__Update.sql 。Java 类名规约不允许存在小数点,所以Java 类名中版本号的数字间只能以下划线进行分隔。
  1. 创建maven环境
  2. image
  3. 增加flyway依赖
            <dependency>
                <groupId>com.googlecode.flyway</groupId>
                <artifactId>flyway-core</artifactId>
                <version>2.3</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
  4. 整合flyway
     Flyway flyway = new Flyway();
     flyway.setInitOnMigrate(true);//Whether to automatically call init when migrate is executed against a non-empty schema with no metadata table.
     flyway.setInitVersion("0");//设置初始化版本
     flyway.setDataSource(dataSource);
     flyway.setTable(databaseMigrateInfo.getTable());//设置存放flyway metadata数据的表名 
     flyway.setLocations(new String[] { databaseMigrateInfo
                        .getLocation() });//设置flyway扫描sql升级脚本、java升级脚本的目录路径或包路径
     flyway.migrate();

注意:1.会生成版本管理表;

           2.版本号可以从0开始,可以设置初始化版本;

           3.代码地址:https://github.com/humeng126/flyway

posted @ 2014-04-13 20:33  humeng126  阅读(3479)  评论(0编辑  收藏  举报