/ other

Flyway入门

Flyway

 Flyway 的中文文档近乎为零,英文文档也凤毛麟角,但它却是我们最理想的数据库版本管理工具,

特性

  • 自动升级(自动发现更新项):Flyway 会将任意版本的数据库升级到最新版本。Flyway 可以脱离JVM 环境通过命令行执行,可以通过Ant 脚本执行,通过Maven 脚本执行(这样就可以在集成环境自动执行),并且可以在应用中执行(比如在应用启动时执行)。
  • 规约优于配置:Flyway 有一套默认的规约,所以不需要修改任何配置就可以正常使用
  • 既支持SQL 脚本,又支持Java 代码:可以使用SQL 脚本执行数据库更新,也可以使用Java 代码来进行一些高级数据升级操作
  • 高可靠性:在集群环境下进行数据库升级是安全可靠的
  • 支持清除已存在的库表结构:Flyway 可以清除已存在的库表结构,可以从零开始搭建您的库表结构,并管理您的数据库版本升级工作
  • 支持失败修复。新的2.0 版本提供了repair 功能,用于解决数据库更新操作失败问题

运行

  1. cmd
    1.  修改conf/flyway.properties  配置文件
    2.  拷贝数据库jdbc  驱动jar  到jars/  目录
    3. 在sql/  目录下创建配置好的sql  脚本文件目录路径,如flyway 默认的sql  文件路径为db/migration ,我们就需要在sql/  目录下创建/db/migration  目录结构
    4.  将数据库维护脚本放到创建好的sql  脚本文件目录中(维护脚本文件名需要遵循命名规范)
    5.  在命令行执行命令(从flyway 安装目录开始执行)flyway init (初始化Flyway metadata )、flyway migrate(执行Flyway 升级操作)、flyway validate (校验Flyway 数据正确性)

2.maven

  • mvn flyway:init
  • mvn flyway:migrate
  • mvn flyway:validate
 <plugin>  
       <groupId>com.googlecode.flyway</groupId>  
       <artifactId>flyway-maven-plugin</artifactId>  
       <version>3.1</version>  
        <dependencies>  
              <dependency>  
                     <groupId>mysql</groupId>  
                     <artifactId>mysql-connector-java</artifactId>  
                     <version>${mysql.connector.version}</version>  
              </dependency>  
       </dependencies>  
       <configuration>  
              <driver>com.mysql.jdbc.Driver</driver>  
              <url>jdbc:mysql://localhost/flywaydemo?useUnicode=true&amp;characterEncoding=utf-8</url>  
              <user>root</user>  
              <password></password>  
              <!-- 设置接受flyway进行版本管理的数据库,多个数据库以逗号分隔 -->  
              <schemas>flywaydemo</schemas>  
              <!-- 设置存放flyway metadata数据的表名 -->  
              <table>schema_version</table>  
              <!-- 设置flyway扫描sql升级脚本、java升级脚本的目录路径或包路径 -->  
              <locations>  
                     <location>flyway/migrations</location>  
                     <location>com.kedacom.flywaydemo.migrations</location>  
              </locations>  
              <!-- 设置sql脚本文件的编码 -->  
              <encoding>UTF-8</encoding>  
              <!-- 设置执行migrate操作之前的validation行为 -->  
              <validationMode>ALL</validationMode>  
              <!-- 设置当validation失败时的系统行为 -->  
              <validationErrorMode>FAIL</validationErrorMode>  
       </configuration>  
	33. 
</plugin> 

3.java

public class FlywayMigration {  
    private DataSource dataSource;  
    public void setDataSource(DataSource dataSource) {  
        this.dataSource = dataSource;  
    }  
  
    public void migrate() {  
        Flyway flyway = new Flyway();  
        flyway.setDataSource(dataSource);  
  
        flyway.setSchemas("flywaydemo"); // 设置接受flyway进行版本管理的多个数据库  
        flyway.setTable("schema_version"); // 设置存放flyway metadata数据的表名  
        flyway.setLocations("flyway/migrations", "com.kedacom.flywaydemo.migrations"); // 设置flyway扫描sql升级脚本、java升级脚本的目录路径或包路径  
        flyway.setEncoding("UTF-8"); // 设置sql脚本文件的编码  
        flyway.setValidationMode(ValidationMode.ALL); // 设置执行migrate操作之前的validation行为  
        flyway.setValidationErrorMode(ValidationErrorMode.FAIL); // 设置当validation失败时的系统行为  
  
        flyway.migrate();  
    }  
  
} 

4.spring

<bean id="flywayMigration" class="com.kedacom.flywaydemo.FlywayMigration" init-method="migrate">  
    <property name="dataSource" ref="dataSource" />  
</bean>  

flywayMigration 这个bean 实例注入了一个数据源,Flyway 的所有操作将针对这个数据源进行;同时我们通过init-method 属性指定了Spring 在实例化该bean 以后,主动执行该bean的migrate 方法,而该方法内会执行Flyway 更新数据库的操作。至此,我们达到了在应用启动时,Spring 实例化上下文的时候,在Spring 实例化flywayMigration 这个bean 的时候,自动执行Flyway 更新数据库的操作。
问题1: 当flyway 还在更新数据库,没有完成更新操作之前,应用程序的其他逻辑已经开始使用数据库进行其他操作了,会导致应用程序产生很多bug

解决办法:

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" depends-on="flywayMigration">  
    <property name="dataSource" ref="dataSource" />  
</bean>  
  
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" depends-on="flywayMigration">  
    <property name="dataSource" ref="dataSource" />  
</bean>  

总结