Flyway spring boot + java,由hibernate创建的新本地数据库,但现在迁移尝试应用已经发生的迁移
Posted
技术标签:
【中文标题】Flyway spring boot + java,由hibernate创建的新本地数据库,但现在迁移尝试应用已经发生的迁移【英文标题】:Flyway spring boot + java, new local database created by hibernate but now migrate tries to apply migrations that already happened 【发布时间】: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
同样的错误
【问题讨论】:
【参考方案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
【讨论】:
以上是关于Flyway spring boot + java,由hibernate创建的新本地数据库,但现在迁移尝试应用已经发生的迁移的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot + Flyway + AWS:原因:java.sql.SQLException:找不到合适的驱动程序
Spring Boot 2.1.0 和 Flyway 4.2.0
Flyway spring boot + java,由hibernate创建的新本地数据库,但现在迁移尝试应用已经发生的迁移
具有 JPA 依赖关系的 Flyway Spring Boot Autowired Bean
Spring Boot学习总结(27)—— Spring Boot中两个数据库迁移工具Liquibase和Flyway的比较
Spring Boot学习总结(27)—— Spring Boot中两个数据库迁移工具Liquibase和Flyway的比较