使用 Flyway 按环境有条件地加载数据

Posted

技术标签:

【中文标题】使用 Flyway 按环境有条件地加载数据【英文标题】:Using Flyway to load data conditionally per environment 【发布时间】:2015-03-10 16:06:22 【问题描述】:

flyway 是否支持按环境条件执行脚本?

例如,如果我有测试数据,是否可以创建一个仅在环境配置为测试时才加载的测试数据脚本文件夹?

【问题讨论】:

是的。看到这个答案:***.com/questions/13153104/… 【参考方案1】:

对于未来的访问者,这是针对特定数据库 sql 的解决方案,但也适用于数据加载。 https://flywaydb.org/documentation/faq#db-specific-sql

您可以设置 flyway.locations=sql/common,sql/data 属性,并且可以使用 spring 配置文件(dev/test/prod)将其设置为不同的值,省略生产中的 sql/data 脚本。

【讨论】:

配合spring boot使用时,已更新为spring.flyway.locations=classpath:sql/common,classpath:sql/data。对于版本 flyway-core:5.0.7【参考方案2】:

Maven 配置文件没有给我想要的灵活性。我想出了一个使用 ant 合并文件的策略。这使我可以拥有通用脚本,然后根据部署类型包含其他数据,例如。产品,开发。

这是我的项目结构:

├── build.xml
├── database.properties
├── database.properties.template
├── lib
│   └── ant-contrib-1.0b3.jar
├── pom.xml
└── sql
    ├── common
    │   ├── V1.0__.sql
    │   ├── V1.2.1__.sql
    │   └── V1.3__.sql
    ├── dev
    │   ├── V1.0__.sql
    │   └── V1.3__.sql
    └── prod
        └── V1.0__.sql

database.properties.template 文件在根目录下,运行前必须手动复制到database.properties 并输入用户名和密码。 database.properties 应该被 VCS 忽略,这样密码就不会出现在 repo 中。

deployType 脚本被合并到 src/main/resources/db/migrate 目录中,这里是执行此操作的 ant 脚本,请注意要合并的脚本具有相同的名称:

<project name="data" default="prepareSql">

    <property file="database.properties" />
    <property name="destDir" value="src/main/resources/db/migration" />

    <echo message="Deploy type: $deployType"/>

    <taskdef resource="net/sf/antcontrib/antcontrib.properties">
      <classpath>
        <pathelement location="lib/ant-contrib-1.0b3.jar"/>
      </classpath>
    </taskdef>

    <target name="prepareSql">
        <!-- ensure the dest dir exists -->
        <mkdir dir="$destDir"/>

        <!-- clear out the dest dir -->
        <delete>
            <fileset dir="$destDir">
                <include name="*" />
            </fileset>
        </delete>

        <!-- append the deploy type files to the common files, delegate to the append target -->
        <foreach target="append" param="file">
            <fileset dir="sql/common" casesensitive="yes">
                <include name="*" />
            </fileset>
        </foreach>
    </target>

    <target name="append">
        <basename property="basename" file="$file" />
        <property name="destFile" value="$destDir/$basename"/>
        <echo message="Appending $file to $destFile" />

        <concat destfile="$destFile" >
            <filelist dir="sql/common" files="$basename" />
            <filelist dir="sql/$deployType" files="$basename" />
        </concat>
    </target>
</project>

这个ant文件是maven执行的,这里是pom配置:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>data</groupId>
    <artifactId>data</artifactId>
    <version>1.1-SNAPSHOT</version>
    <packaging>pom</packaging>
    <name>data</name>

    <properties>
        <sqlBaseDir>filesystem:$basedir/src/main/resources/</sqlBaseDir>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <version>1.7</version>
                <executions>
                    <execution>
                        <id>mergeScripts</id>
                        <phase>validate</phase>
                        <inherited>false</inherited>
                        <configuration>
                            <target>
                                <ant antfile="build.xml" target="prepareSql" />
                            </target>
                        </configuration>
                        <goals>
                            <goal>run</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-maven-plugin</artifactId>
                <version>3.2.1</version>
                <configuration>
                    <schemas>
                        <schema>common</schema>
                    </schemas>
                    <configFile>database.properties</configFile>
                    <table>flyway</table>
                    <locations>
                        <location>filesystem:$basedir/src/main/resources/db/migration</location>
                    </locations>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.36</version>
        </dependency>
    </dependencies>
</project>

如果您需要为不同的客户端分发提供不同的数据,您可以将 dist 目录添加到 sql 目录中,它们可以包含 deployType 子目录。

将 dist 属性添加到 database.properties.template 文件中,然后将 build.xml 中的 append 目标修改为如下所示:

<target name="append">
    <basename property="basename" file="$file" />
    <property name="destFile" value="$destDir/$basename"/>
    <echo message="Appending $file to $destFile" />

    <concat destfile="$destFile" >
        <filelist dir="sql/common" files="$basename" />
        <filelist dir="sql/$deployType" files="$basename" />
            <filelist dir="sql/$dist/common" files="$basename" />
            <filelist dir="sql/$dist/$deployType" files="$basename" />
    </concat>
</target>

【讨论】:

【参考方案3】:

如果您使用的是 maven,您可以通过 maven 配置文件概念非常轻松地实现它。请参考以下示例

pom.xml

<plugin>
    <groupId>com.googlecode.flyway</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <url>jdbc:sqlserver://$db.hostname;databaseName=$db.name</url>
        <user>$db.username</user>
        <password>$db.password</password>
        <initVersion>0</initVersion>
        <initDescription>Base Migration</initDescription>
        <table>Changelog_testproject</table>
        <locations>
           <location>filesystem:$sql.file.path</location>
        </locations>
    </configuration>
</plugin>

<profiles>
    <profile>
        <id>dev</id>
        <properties>
            <profile.name>dev</profile.name>
            <sql.file.path>$basedir/deploy/dev/sqldelta/sqlserver</sql.file.path> 
            <db.hostname>127.0.0.1:1433</db.hostname>
            <db.name>dev</db.name>
            <db.username>dev</db.username>
            <db.password>devadmin</db.password>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <profile.name>test</profile.name>
            <sql.file.path>$basedir/deploy/test/sqldelta/sqlserver</sql.file.path>  
            <db.hostname>127.0.0.1:1433</db.hostname>
            <db.name>test</db.name>
            <db.username>test</db.username>
            <db.password>testadmin</db.password>
        </properties>
    </profile>
 </profiles>

flywayflywaydb

【讨论】:

什么是 $base.dir。是“src/main/java >> files here”..还是资源的基本目录?【参考方案4】:

您可以使用flyway占位符

在您的环境 config.properties 上配置它:

flyway.placeholders.tableName=MY_TABLE

flyway.placeholders.name='Mr.测试'

然后,把它放在你的脚本上: 插入 $tableName(名称)值($name);

我也使用过 flyway.locations,但占位符比简单更改的位置更简单。

【讨论】:

这似乎不是问题的答案。

以上是关于使用 Flyway 按环境有条件地加载数据的主要内容,如果未能解决你的问题,请参考以下文章

如何最好地处理带有嵌入式数据库的 Flyway 以进行集成测试?

数据库数据升级,按环境进行版本控制

如何在多架构 MS SQL Server 环境中使用 Flyway?

php 根据环境$ _SERVER ['HTTP_HOST']有条件地将配置文件加载到wp_config中

Flyway - Version control for your database

将环境变量传递给 Docker 时,Flyway 迁移失败