# mvcFlyway
**Repository Path**: zhanght_admin/mvcFlyway
## Basic Information
- **Project Name**: mvcFlyway
- **Description**: 搭建基于SpringMVC的flyway数据库版本管理-web应用
- **Primary Language**: Java
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2017-10-24
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
#mvcFlyway
----------------
##1、基本概念
###1.1、Spring
Spring是一个**开源框架**,Spring是于2003 年兴起的一个轻量级的**Java** 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 简单来说,Spring是一个轻量级的控制反转(**IoC**)和面向切面(**AOP**)的容器框架。
###1.2、SpringMVC
Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面。Spring MVC 分离了**控制器、模型对象、分派器**以及处理程序对象的角色,这种分离让它们更容易进行定制。
###1.3、MyBatis
MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。MyBatis是一个基于**Java的持久层**框架。iBATIS提供的持久层框架包括SQL Maps和Data Access Objects(DAO)MyBatis 消除了几乎所有的JDBC代码和参数的手工设置以及结果集的检索。MyBatis 使用简单的 XML或注解用于配置和原始映射,将接口和 Java 的POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录。
##2、搭建开发环境
如果需要,参看之前的博文:http://blog.csdn.net/zhshulin/article/details/30779873
##3、Maven Web项目创建
如果需要,参看之前的博文:http://blog.csdn.net/zhshulin/article/details/37921705
##4、SSM整合
SSM整合可参考如下文章:http://blog.csdn.net/gebitan505/article/details/44455235/
下面主要介绍三大框架的整合,至于环境的搭建以及项目的创建,参看上面的博文。这次整合我分了2个配置文件,分别是spring-mybatis.xml,包含spring和mybatis的配置文件,还有个是spring-mvc的配置文件,此外有2个资源文件:jdbc.propertis和log4j.properties。完整目录结构如下(最后附上源码下载地址,不建议直接使用源码,因为此教程已经有了全部代码)。
使用框架都是较新的版本:
Spring 4.0.2 RELEASE
Spring MVC 4.0.2 RELEASE
MyBatis 3.2.6
###4.1、Maven引入需要的JAR包
为了方便后面说的时候不需要引入JAR包,我这里直接给出所有需要的JAR包,这都是基本的JAR包,每个包的是干什么的都有注释,就不再多说了。 **pom.xml**
##5、flyway-数据库版本管理学习
###5.1 引言
随着项目不断的增大,尤其是一个在不断开发完善的项目,随着需求变化,数据库的schema也会跟着变化,数据库也需要不断的扩充,加表加字段,(每一次的增加称作一次DB的迁移migration)你是否还在用着最原始的方式, 用文件管理每次的SQL升级脚本,加了哪些字段,加了那些表,现在可以用数据库版本控制工具-flyway轻而易举搞定了。

**flyway**是一个简单开源的数据库版本控制器,它支持SQL(PL/SQL、T-SQL)方式和Java方式,可以和spring 框架进行无缝连接,支持命令行客户端等,还提供一系列的插件支持(Maven、Gradle、SBT、ANT等),使其在系统启动的时候检查并升级数据库的版本(特别适合于java项目)。
###5.2 flyway主要特性
- 普通SQL:纯SQL脚本(包括占位符替换)没有专有的XML格式,没有锁定。
- 无限制:使用Java 代码来进行一些高级数据操作
- 零依赖:只需运行在Java6(及以上)和数据库所需的JDBC驱动
- 约定优于配置:迁移时,自动查找系统文件和类路径中的SQL文件或Java类
- 高可靠性:在集群环境下进行数据库升级是安全可靠的
- 云支持:完全支持 Microsoft SQL Azure, Google Cloud SQL& App Engine、Heroku Postgres 和 Amazon RDS
- 自动迁移:使用Flyway提供的API,让应用启动和迁移同时工作
- 快速失败:损坏的数据库或失败的迁移可以防止应用程序启动
- 数据库清理:在一个数据库中删除所有的表、视图、触发器,而不是删除数据库本身
###5.3 支持的数据库
- Oracle:10g及更新所有版本(包括 Amazon RDS)
- SQL Server:2008及更新版本(包括 Amazon RDS)
- SQL Azure:最新版本
- MySQL:5.1及更新版本(包括 Amazon RDS & Google Cloud SQL)
- MariaDB:10.0及更新版本(包括 Amazon RDS)
- Phoenix:4.2.2及更新版本
- PostgreSQL:9.0及更新版本(包括 Heroku & Amazon RDS)
- Vertica:6.5及更新版本
- AWS Redshift:最新版本
- DB2:9.7及更新版本
- DB2 z/OS:9.1及更新版本
- Derby:10.8.2.2及更新版本
- H2:1.2.137及更新版本
- Hsql:1.8及更新版本
- SQLite:3.7.2及更新版本
- SAP HANA:最新版本
- solidDB:6.5及更新版本
- Sybase ASE:12.5及更新版本
###5.4 flyway基本概念、命令及脚本命名规则
#### 1) 基本概念
版本:对数据库的每一次变更可称为一个版本。
迁移:Flyway把数据库结构从一个版本更新到另一个版本叫做迁移。
可用的迁移:Flyway的文件系统识别出来的迁移版本。
已经应用的迁移:Flyway已经对数据库执行过的迁移。
#### 2) 几个命令
Migrate:应用所有的迁移到最新版本,它会在你的DB中新建个表schema_version来存放每次升级的版本信息。
Clean:clean all objects
Info:打印所有的迁移的信息以及状态。
Validate:迁移之前进行验证。
Baseline:初始化schema_version表,并插入一条原始verion=1。
Repair:它主要做了两件事,移除所有失败的迁移(升级),重置校验和。
#### 3) sql脚本命名规则
prefix: default: V (大写哦)
version: 版本号,也可以使用大小版本组合的方式,小版本号用单 _区分
separator: 分隔符,双下划线 __
description: 描述(你懂得,必须要有意义)
suffix: 后缀 default: .sql
例如: `V1_0_0__Init.sql V1_1_0__Update.sql`
默认prefix是V(执行一遍,并且版本号唯一,如果有重复就会报错)或R(重复执行,不需要版本号),separator是双下划线__,suffix是.sql

###5.5 flyway工作原理
场景是当你用Flyway迁移到一个空数据库时:

Flyway将会试图查找数据库中的元数据表(metadata table)。由于数据库是空的,Flyway 将不会查找,而是创建一个新元数据表。
现在数据库中将有一张名为SCHEMA_VERSION的表:

此表将用于跟踪数据库的状态。
之后,使用Flyway进行迁移时将扫描系统文件或者应用的类路径中特定的文件,它们可以由SQL或Java编写。
然后Flyway将基于他们的版本号进行排序并依次执行:

随着每次执行,对应地更新元数据表:
schema_version表

元数据表的创建和初始化,我们现在可以讨论迁移到一个新的版本。
Fly进行迁移时会重新扫描系统文件或者应用的类路径中特定的文件,并且与元数据表进行校验,如果它们的版本号低于或等于当前标记的版本,它们将被忽略。
而高于标记的文件将等待迁移:状态为可用(available),但是未执行 。

Flyway会将它们按照版本号进行排序并依次执行。

元数据表相应的更新:
schema_version表

从而使得我们可以非常容易的创建一个高于当前标记版本的迁移文件,用来更新数据库,无论是表结构的变化或是数据的更新。下次Flyway开始迁移时,它会找到这个文件并相应更新数据库。
###5.6 flyway—命令行操作
* 首先从官网下载压缩包:[https://flywaydb.org/documentation/commandline/](https://flywaydb.org/documentation/commandline/ "命令行压缩包下载")
解压后cd到目录下,就可以直接执行flyway。解压后的文件夹结构如下图:

如果操作数据库,需要先在/conf/flyway.conf文件中做下配置,主要是对flyway.url、flyway.user和flyway.password,注释中给出了url的详细格式,可以根据环境自行添加。
实例:
这里以mysql为例,在 flyway.conf中进行相关配置即可。

###5.7 SpringMVC整合flyway
#### 1) Java API配置flyway
1. 引入flyway的jar包,在pom.xml里面内容如下:
2.3
com.googlecode.flyway
flyway-core
${flyway.version}
commons-logging
commons-logging
2. 编写数据库的版本的脚本文件,放到/src/main/resources的flyway里面(在本测试项目中我把flyway改为DBFiles了)。
(flyway找脚本的时候默认去/src/mian/resources下面的db/migration,如果要放在别的位置,后面的地方要配置一下)
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();
}
}
}
4. 设置在系统启动是自动运行DatabaseFlywayMigration类的migrate方法
在applicationContext.xml(spring mvc的上下文中加入如下:)
从上面的bean 定义中我们可以看到,我们为flywayMigration 这个bean 实例注入了一个数据源,Flyway 的所有操作将针对这个数据源进行;同时我们通过init-method 属性指定了Spring 在实例化该bean 以后,主动执行该bean 的migrate 方法,而该方法内会执行Flyway 更新数据库的操作。
至此,我们达到了在应用启动时,Spring 实例化上下文的时候,在Spring 实例化flywayMigration 这个bean 的时候,自动执行Flyway 更新数据库的操作。
但是,我们还没有达到目的,万一Flyway 还在更新数据库,没有完成更新操作之前,应用程序的其他逻辑已经开始使用数据库进行其他操作了,会导致应用程序产生很多bug ,甚至根本运行不起来。
要解决这个问题,我们可以利用Spring 的bean 依赖原理,让关键的数据库操作bean 依赖于flywayMigration 这个bean ,达到在flywayMigration 没有实例化完成(数据库更新操作完成)之前,不能进行任何其他数据库相关操作。
5. 利用Spring 的bean 依赖让flywayMigration 优先处理数据库更新操作:
至此,运行就可以了。
#### 2) applicationContext.xml 配置flyway
这样web app在启动后,在加载applicationContext.xml的同时,会读取flyway配置,从而达到一种数据迁移的效果。