随着项目不断的增大,尤为是一个在不断开发完善的项目,随着需求变化,数据库的schema也会跟着变化,数据库也须要不断的扩充,加表加字段,(每一次的增长称做一次DB的迁移migration)你是否还在用着最原始的方式, 用文件管理每次的SQL升级脚本,加了哪些字段,加了那些表,如今能够用数据库版本控制工具垂手可得搞定了。html
flyway支持java API的操做方式,能够和spring 框架进行无缝链接,使其在系统启动的时候检查并升级数据库的版本(特别适合于java项目)。java
版本:对数据库的每一次变动可称为一个版本。spring
迁移:Flyway把数据库结构从一个版本更新到另外一个版本叫作迁移。sql
可用的迁移:Flyway的文件系统识别出来的迁移版本。数据库
已经应用的迁移:Flyway已经对数据库执行过的迁移。tomcat
Migrate:应用全部的迁移到最新版本,它会在你的DB中新建个表schema_version
来存放每次升级的版本信息。mvc
Clean:clean all objects框架
Info:打印全部的迁移的信息以及状态。ssh
Validate:迁移以前进行验证。maven
Baseline:初始化schema_version
表,并插入一条原始verion=1。
Repair:它主要作了两件事,移除全部失败的迁移(升级),重置校验和。
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哦。
这儿就不详细介绍了。这个不是重点。重点在介绍java的使用
有以下插件支持:Maven, Gradle,SBT和Ant,还有更多Plugins,提供对Spring Boot, Dropwizard, Grails, Play, Griffon, Grunt, Ninja 的支持。 其中能够研究下flyway-test-extensions,有Usage flyway dbunit test、Usage-flyway-spring-test 功能很强大。
<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>
(flyway找脚本的时候默认去/src/mian/resources下面的db/migration,若是要放在别的位置,后面的地方要配置一下)
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(); } } }
在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版本是这样的,不知道后面的版本有没有改善这个问题。