【问题标题】:Flyway spring boot + java, new local database created by hibernate but now migrate tries to apply migrations that already happenedFlyway spring boot + java,由hibernate创建的新本地数据库,但现在迁移尝试应用已经发生的迁移
【发布时间】:2021-05-25 00:19:17
【问题描述】:

我最初使用 hibernate 创建项目以像大多数人一样创建表,但随后我开始使用 flyway 进行数据库迁移。

问题是我删除了包括 db 在内的整个本地系统并尝试再次旋转它,但我遇到了休眠和飞行路径的冲突。

顺便说一下,我正在使用 java api。所以当我去本地重建数据库时我打开了 spring.jpa.hibernate.ddl-auto=${HIBERNATE_DDL:create} 只是第一次运行,然后转过来验证

所以它构建了所有表,但是现在当我尝试启动应用程序时,它会尝试运行第一个迁移

ALTER TABLE public.auth ADD COLUMN resent boolean

这将导致启动时出错,因为该新列是由休眠添加的

Error Code : 0
Message    : ERROR: column "resent" of relation "auth" already exists
Location   : db/migration/V1__Add_Resent_To_Auth.sql (/Users/brian/code/slap/build/resources/main/db/migration/V1__Add_Resent_To_Auth.sql)
Line       : 1
Statement  : ALTER TABLE public.auth
    ADD COLUMN resent boolean

那么我如何告诉 flyway 当前版本是 V9 并且仅在此之后运行迁移。它不应该只是查看 flyway_schema_history 并查看版本 9 是最后一个条目,然后再运行迁移吗?我一定是错过了什么

我尝试在我的配置中这样做以首先设置基线版本

@Configuration
class FlyWay() {

    @Value("\${spring.datasource.url}")
    lateinit var url: String

    @Value("\${spring.datasource.username}")
    lateinit var username: String

    @Value("\${spring.datasource.password}")
    lateinit var password: String

    @Bean
    fun migrate() {
        val flyway = Flyway.configure().baselineVersion("9.0").dataSource(url, username, password).load()
        flyway.migrate()
    }
}

没有这样的运气,它仍然尝试运行 V1

我也尝试将它添加到 application.properties spring.flyway.baselineVersion=9.0 同样的错误

【问题讨论】:

    标签: spring spring-boot hibernate flyway


    【解决方案1】:

    我理解的场景:

    • 表已经存在
    • 表的状态对应于版本“9.0”
    • 应为本地测试数据库设置一次 Flyway 基线版本

    通过命令行设置版本可能很有用,因为它只应用于测试数据库一次,然后将应用正常的迁移策略。

    文档见:https://flywaydb.org/documentation/usage/commandline/baseline

    在 macOS 上,可以使用 brew install flyway 安装 Flyway 命令行客户端。

    说明

    • 确保删除表 flyway_schema_history。使用您首选的 SQL 客户端:
       drop table flyway_schema_history;
    
    • 然后使用 Flyway 命令行客户端设置基线版本(本示例使用 Postgres 数据库):
       flyway -user=stephan -password= -url=jdbc:postgresql://localhost:5432/stephan -baselineVersion="9.0" -locations="src/main/resources/db/migration" baseline
    
    • 签入 SQL 客户端:
    select version from flyway_schema_history ;
    

    现在应该显示“9.0”。之后,Spring Boot 应用程序应该像往常一样运行。

    测试

    替代方案

    对于喜欢使用 Maven 命令执行此操作的人:

    • 如上所示删除表 flyway_schema_history
    • 使用命令mvn flyway:baseline -Dflyway.baselineVersion="9.0" 设置基线版本

    这需要在pom.xml 文件中进行一些配置,例如如果使用 Postgres 数据库:

    <build>
        ...
        <plugins>
            ...
            <plugin>
                <groupId>org.flywaydb</groupId>
                <artifactId>flyway-maven-plugin</artifactId>
                <version>7.1.1</version>
                <configuration>
                    <url>jdbc:postgresql://localhost:5432/stephan</url>
                    <user>stephan</user>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.postgresql</groupId>
                        <artifactId>postgresql</artifactId>
                        <version>42.2.18</version>
                    </dependency>
                </dependencies>
            </plugin>
        ...
    

    使用 Maven 进行测试

    快速测试显示相同的结果。

    【讨论】:

      【解决方案2】:

      为什么不从您的数据库(由 Hibernate 创建)导出 SQL 脚本并将其作为第一个 Flyway 脚本添加到您的应用程序中?这是最干净的解决方案,因为当应用程序将在其他系统上运行时,不需要再次手动启动 Hibernate。

      【讨论】:

      • 我想办法做到这一点,但找不到解决方案,我也无法在生产中搞乱数据
      • 我没有读到有生产数据库。我仍然会采用这种方法并将基线属性专门用于生产。如果设置更容易,作为替代方案,在本地运行应用程序并将 flyway_schema_history 表(包含已执行脚本的条目)复制到生产环境,因此不需要基线。
      • 基线属性不起作用,这就是问题所在,我需要告诉 flyway 它在版本 9 上的方式
      • 我认为它应该是baselineVersionAsString 属性。但是我在网上找不到可靠的信息,所以也许复制历史记录表是一个更快的选择。
      【解决方案3】:

      在您的 application.yml 中添加以下行后尝试一次 spring.flyway.baseline-on-migrate: true

      【讨论】:

        猜你喜欢
        • 2019-02-06
        • 2020-10-17
        • 2018-03-31
        • 2018-10-07
        • 2018-08-16
        • 2020-07-20
        • 2021-08-08
        • 2020-08-20
        相关资源
        最近更新 更多