在 Flyway Java API 中使用 SQL 迁移文件

Posted

技术标签:

【中文标题】在 Flyway Java API 中使用 SQL 迁移文件【英文标题】:Use an SQL migration file in the Flyway Java API 【发布时间】:2017-01-07 05:40:51 【问题描述】:

我不确定这是否可行,但我正在尝试通过 Flyway Java API 以编程方式加载保存在 SQL 文件中的迁移。我有一个 SQL 文件保存在基类路径中(现在为了简单起见)作为 V1__Initial_version.sql 并带有一个简单的表创建语句:

CREATE TABLE test_user (
    name VARCHAR(25) NOT NULL, PRIMARY KEY(name)
);

然后在我使用的Java程序中

Flyway flyway  = new Flyway();
flyway.setDataSource(jdbc_url, user, password);
int migrations = flyway.migrate();  // Just to check the # of migrations applied

我看到 ClassPathScanner 在类路径中查找有效迁移,但它似乎忽略了 sql 迁移文件。当我从命令行调用 flyway migrate 时,相同的 sql 迁移文件工作正常。我创建了一个 java 类并从 JdbcMigrations 类继承,ClassPathScanner 可以很好地选择它。我需要做什么才能让 Java ClassPathScanner 拾取 .sql 文件并将其用作有效迁移?

更大的画面

也许我一开始就错误地处理了这个问题,所以我将添加我正在尝试做的事情。我正在尝试设置一个测试数据库,我可以在测试之间使用、核对和重建。 IE。 TestA 在表中输入一些内容,然后预测试函数将清理 DB 并重置它,然后 TestB 将有一个干净的 DB 和空表来执行它的测试。我在预测试函数中使用 flyway.clean() 和 flyway.migrate() 但它破坏了 schema_version 表以及其他所有内容,然后迁移不会从以前的基线重建。

感谢任何帮助!谢谢!

【问题讨论】:

我不太明白对架构进行核对的意义。数据,是的,但是架构?我会使用 DbSetup (dbsetup.ninja-squad.com)。免责声明:我是作者。 你是对的,真的没有必要对架构进行核对。我要做的就是清除数据,但使用 flyway.clear 也会删除我的模式表。我没有看到 flyway 清除数据但保留表和架构的另一种方法。 这不是 Flyway 的用途。 Flyway 的工作是进行模式演变。 谢谢!这解决了部分麻烦! 我的大多数单元测试都使用内存数据库,所以在测试运行后,模式无论如何都消失了(但为了确保表在测试之间为空,我在 @Before 固定方法中使用 JDBC 删除) . 【参考方案1】:

不知道为什么它没有接收到您的任何迁移。也许他们需要在一个特定的目录中?您需要检查 src 代码以了解它为什么不选择您的文件进行迁移。

关于大局:

我们通常在运行构建和测试用例之前使用 flyway:migrate 迁移测试数据库。我们使用 DBUnit、Spring 测试或类似的单元测试框架,它们允许使用数据进行预测试 DB 设置。在测试期间结构不应改变,因此不需要数据库迁移。 Arquillian 在运行测试之前对数据库初始化也非常有用,请参阅此处https://github.com/arquillian/arquillian-extension-persistence

编辑 1 所以我创建了一个小例子

import org.flywaydb.core.Flyway;
public class TestClass 
public static void main(String args[]) 
    Flyway flyway = new Flyway();
    for (String location : flyway.getLocations()) 
        System.out.println(location);
    
    flyway.setDataSource("jdbc:h2:~/test", "sa", "");
    System.out.println("Result: " + flyway.migrate());


将sql文件放入src/main/resources/db/migration并运行。它可以很好地进行 sql 迁移。如果要将 sql 放在不同的目录中,请使用 setLocations()

classpath:db/migration
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.util.VersionPrinter printVersion
INFO: Flyway 4.0.3 by Boxfuse
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.dbsupport.DbSupportFactory createDbSupport
INFO: Database: jdbc:h2:~/test (H2 1.4)
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.command.DbValidate validate
INFO: Successfully validated 1 migration (execution time 00:00.009s)
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.command.DbMigrate migrate
INFO: Current version of schema "PUBLIC": << Empty Schema >>
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.command.DbMigrate applyMigration
INFO: Migrating schema "PUBLIC" to version 1.1 - Initial version
Result: 1
Aug 30, 2016 10:48:41 PM org.flywaydb.core.internal.command.DbMigrate logSummary
INFO: Successfully applied 1 migration to schema "PUBLIC" (execution time 00:00.024s).

【讨论】:

我已将sql迁移文件放在与java类迁移相同的位置,在flyway查看的类路径中。java类确实被拾取,sql文件没有。 您将使用我提到的数据库单元测试框架之一。清除数据库可以是一个简单的 SQL,它禁用所有约束并截断所有表。使用 flyway 为每个测试构建一个数据库模式将无法很好地扩展,尤其是当您有更多的数据库迁移和更多的测试时。 谢谢,这与 JB Nizet 在 cmets 中给出的建议类似,并解决了部分问题。我仍然想从 sql 而不是 java JdbcMigration 类中获取基本迁移。 我仍然不建议这样做。只需在运行测试之前运行 mvn flyway:migrate 即可。我已经编辑了我的问题以提供一个工作示例,只是为了回答您的请求:-) 谢谢!这可以创建 sql 架构并将其添加到 db/migration 目录,但在我尝试设置位置时却不行。我认为那里存在权限问题,但这肯定回答了这个问题!我也会考虑更新构建中的架构,这可能会更聪明!

以上是关于在 Flyway Java API 中使用 SQL 迁移文件的主要内容,如果未能解决你的问题,请参考以下文章

为啥 flyway 会忽略我的 SQL 迁移文件?

在运行时在 Java 代码中运行 flyway 迁移

使用 flyway 占位符生成 sql 语句

Spring Boot + Flyway + AWS:原因:java.sql.SQLException:找不到合适的驱动程序

Flyway 未接收 Java 迁移

MariaDB 和 flyway 语法错误,但在 JAVA 中没有