Created
May 5, 2017 06:42
-
-
Save x10w50/1bd5952340c825c7d9acd851933ff6ee to your computer and use it in GitHub Desktop.
flyway
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* http://www.07net01.com/2016/04/1434487.html | |
1.引言 | |
随着项目不断的增大,尤其是一个在不断开发完善的项目,随着需求变化,数据库的schema也会跟着变化,数据库也需要不断的扩充,加表加字段,(每一次的增加称作一次DB的迁移migration)你是否还在用着最原始的方式, 用文件管理每次的SQL升级脚本,加了哪些字段,加了那些表,现在可以用数据库版本控制工具轻而易举搞定了。 | |
flyway支持Java API的操作方式,可以和spring 框架进行无缝连接,使其在系统启动的时候检查并升级数据库的版本(特别适合于java项目)。 | |
2.flyway的特点 | |
2.1使用它之前先要了解一些概念: | |
版本:对数据库的每一次变更可称为一个版本。 | |
迁移:Flyway把数据库结构从一个版本更新到另一个版本叫做迁移。 | |
可用的迁移:Flyway的文件系统识别出来的迁移版本。 | |
已经应用的迁移:Flyway已经对数据库执行过的迁移。 | |
2.2 .flyway最基本的几个命令。 | |
Migrate:应用所有的迁移到最新版本,它会在你的DB中新建个表schema_version来存放每次升级的版本信息。 | |
Clean:clean all objects | |
Info:打印所有的迁移的信息以及状态。 | |
Validate:迁移之前进行验证。 | |
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版本是这样的,不知道后面的版本有没有改善这个问题。 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment