java Spring Boot:Hibernate 和 Flyway 引导顺序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37097876/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 02:12:26  来源:igfitidea点击:

Spring Boot: Hibernate and Flyway boot order

javahibernatespring-bootspring-data-jpaflyway

提问by user3636486

I have created Spring application. Pom xml is attached.

我已经创建了 Spring 应用程序。附上 Pom xml。

It has a config like this (below) and some db/migration/V1__init.sql for Flyway db migration tool.

它有这样的配置(如下)和一些用于 Flyway 数据库迁移工具的 db/migration/V1__init.sql。

It has hsqldb in-memory database and it is created after application is started. It is clean after creation.

它有 hsqldb 内存数据库,它是在应用程序启动后创建的。创建后是干净的。

I want Hibernate to create a schema based on entity classes and then Flyway fills the tables. Now Flyway starts V1__init.sql before tables is created and throw an exception. How can I change this order or what solution can I do?

我希望 Hibernate 创建基于实体类的模式,然后 Flyway 填充表。现在 Flyway 在创建表之前启动 V1__init.sql 并抛出异常。如何更改此顺序或我可以采取什么解决方案?

spring.datasource.testWhileIdle = true
spring.datasource.validationQuery = SELECT 1
spring.jpa.show-sql = true
spring.jpa.hibernate.ddl-auto = create-drop
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.HSQLDialect

pom.xml:

pom.xml:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.3.3.RELEASE</version>
    <relativePath/>
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>1.3.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.hsqldb</groupId>
        <artifactId>hsqldb</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-core</artifactId>
        <version>4.3.11.Final</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-orm</artifactId>
        <version>4.2.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.thymeleaf</groupId>
        <artifactId>thymeleaf-spring4</artifactId>
        <version>2.1.4.RELEASE</version>
    </dependency>

    <!-- For using 'LEGACYHTML5' mode in Thymeleaf -->
    <dependency>
        <groupId>net.sourceforge.nekohtml</groupId>
        <artifactId>nekohtml</artifactId>
        <version>1.9.21</version>
    </dependency>
    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>1.4.01</version>
    </dependency>

    <dependency>
        <groupId>org.flywaydb</groupId>
        <artifactId>flyway-core</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
        <version>1.3.3.RELEASE</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

回答by user3707816

I had the same issue.

我遇到过同样的问题。

I wanted my schema to be created by hibernate because of it's database independence. I already went through the trouble of figuring out a nice schema for my application in my jpa classes, I don't like repeating myself.

我希望我的模式由休眠创建,因为它与数据库无关。我已经为我的 jpa 类中的应用程序找出了一个很好的模式,我不喜欢重复自己。

But I want some data initialization to be done in a versioned manner which flyway is good at.

但是我希望以 flyway 擅长的版本化方式完成一些数据初始化。

Spring boot runs flyway migrations before hibernate. To change it I overrode the spring boot initializer to do nothing. Then I created a second initializer that runs after hibernate is done. All you need to do is add this configuration class:

Spring Boot 在休眠之前运行 Flyway 迁移。为了改变它,我覆盖了 spring boot 初始化器什么都不做。然后我创建了第二个初始化程序,它在休眠完成后运行。你需要做的就是添加这个配置类:

import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

@Configuration
public class MigrationConfiguration {


    /**
     * Override default flyway initializer to do nothing
     */
    @Bean
    FlywayMigrationInitializer flywayInitializer(Flyway flyway) {
        return new FlywayMigrationInitializer(flyway, (f) ->{} );
    }


    /**
     * Create a second flyway initializer to run after jpa has created the schema
     */
    @Bean
    @DependsOn("entityManagerFactory")
    FlywayMigrationInitializer delayedFlywayInitializer(Flyway flyway) {
        return new FlywayMigrationInitializer(flyway, null);
    }


}

That code needs java 8, If you have java 7 or earlier, replace (f)->{}with an inner class that implements FlywayMigrationStrategy

该代码需要 java 8,如果您有 java 7 或更早版本,请替换(f)->{}为实现FlywayMigrationStrategy的内部类

Of course you can do this in xml just as easily.

当然,您可以同样轻松地在 xml 中执行此操作。

Make sure to add this to your application.properties:

确保将其添加到您的 application.properties 中:

flyway.baselineOnMigrate = true

回答by Andy Wilkinson

Spring Boot auto-configuration of Flyway ensures that database migrations have run before Hibernate is initialised. In other words, you can't rely on Flyway auto-configuration and use Flyway to populate tables created by Hinernate.

Flyway 的 Spring Boot 自动配置可确保在初始化 Hibernate 之前已运行数据库迁移。换句话说,您不能依赖 Flyway 自动配置并使用 Flyway 来填充由 Hinernate 创建的表。

One solution is to fully embrace Flyway and use it to both create the tables and populate them. You can then switch off Hibernate's table creation (spring.jpa.hibernate.ddl-auto=none). This approach is more robust as it will allow your database to evolve more easily. This is what I would recommend that you do.

一种解决方案是完全采用 Flyway 并使用它来创建表并填充它们。然后您可以关闭 Hibernate 的表创建 ( spring.jpa.hibernate.ddl-auto=none)。这种方法更强大,因为它可以让您的数据库更轻松地发展。这就是我建议你做的。

Another solution is to disable auto-configuration of Flyway (flyway.enabled=false) and to configure it your self. You can then configure Flyway to depend on Hibernate so that Hibernate has created the tables before Flyway tries to populate them.

另一种解决方案是禁用 Flyway ( flyway.enabled=false) 的自动配置并自行配置。然后,您可以将 Flyway 配置为依赖于 Hibernate,以便 Hibernate 在 Flyway 尝试填充表之前已创建这些表。

回答by pavelety

All SQL migrations will start after Hibernate creates all the tables.

所有 SQL 迁移将在 Hibernate 创建所有表后开始。

Spring Boot 2.2.2, Flyway 6.0.8

Spring Boot 2.2.2,Flyway 6.0.8

To disable boot for Flyway, insert into resources/application.properties:

要禁用 Flyway 启动,请插入 resources/application.properties:

spring.flyway.enabled=false

Create separate configuration for Flyway to make it load when Hibernate is ready:

为 Flyway 创建单独的配置以使其在 Hibernate 准备就绪时加载:

@Configuration
public class FlywayConfiguration {

    @Autowired
    public FlywayConfiguration(DataSource dataSource) {
        Flyway.configure().baselineOnMigrate(true).dataSource(dataSource).load().migrate();
    }
}

Start your migration scripts from version 2:

从版本 2 开始您的迁移脚本:

resources/db.migration/V2__fill-tables.sql

V1 is used as a baseline, V1 file will be ignored.

V1 用作基线,V1 文件将被忽略。

回答by peterzinho16

For more recent users that use Spring Boot +2.1 and as @mota commented into @user3707816's answer, you can use spring.flyway.enabled=falsein application.properties and then create a new instance manually:

对于最近使用 Spring Boot +2.1 的用户以及@mota 在@user3707816 的回答中的评论,您可以在 application.properties 中使用spring.flyway.enabled=false,然后手动创建一个新实例:

Flyway.configure().dataSource(dataSource)
                .baselineOnMigrate(true)
                .schemas(PG_DATABASE_SCHEMA)//optional, by default is public
                .load().migrate();

回答by Jo?o Victor Scanagatta

may be because of the order

可能是因为顺序

add on application.properties

添加 application.properties

flyway.out-of-order = true

or application.yml on spring

或 spring 上的 application.yml

flyway:
  out-of-order: true