2016-05-08 42 views
5

Utworzyłem aplikację Spring. Pom xml jest załączony.Spring Boot: Hibernate and Flyway boot order

Posiada taką konfigurację (poniżej) i trochę db/migration/V1__init.sql dla narzędzia migracji do Flyway db.

Posiada bazę danych hsqldb w pamięci i jest tworzona po uruchomieniu aplikacji. Jest czysty po stworzeniu.

Chcę, aby Hibernate tworzył schemat oparty na klasach encji, a następnie Flyway wypełnia tabele. Teraz Flyway rozpoczyna V1__init.sql przed utworzeniem tabel i generuje wyjątek. Jak mogę zmienić tę kolejność lub jakie rozwiązanie mogę zrobić?

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:

<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> 
+2

niezwiązane z pytaniem, ale należy usunąć wielu wersjach od swojej pom i niech Boot skonfigurować je dla Ciebie. I na pewno nie powinieneś mieszać wersji samego Spring Boot (masz 1.3.2.RELEASE i 1.3.3.RELEASE). –

Odpowiedz

1

mam rozwiązany moje zadanie. Usunąłem Flyway i właśnie dodałem data.sql

8

Automatyczna konfiguracja Spring Boot Flywaya zapewnia, że ​​migracje bazy danych zostały uruchomione przed zainicjowaniem Hibernate. Innymi słowy, nie można polegać na automatycznej konfiguracji Flywaya i używać Flywaya do wypełniania tabel tworzonych przez Hinernate.

Jednym z rozwiązań jest pełne wykorzystanie Flywaya i użycie go do utworzenia tabel i wypełnienia ich. Następnie można wyłączyć tworzenie tabeli Hibernate (spring.jpa.hibernate.ddl-auto=none). Takie podejście jest bardziej niezawodne, ponieważ pozwala na łatwiejszą ewolucję bazy danych. To jest to, co polecam.

Innym rozwiązaniem jest wyłączenie automatycznej konfiguracji Flywaya (flyway.enabled=false) i skonfigurowanie go samodzielnie. Następnie możesz skonfigurować Flyway tak, aby zależało od Hibernate, aby Hibernate stworzył tabele, zanim Flyway spróbuje je zapełnić.

+1

Czy masz przykładowy kod drugiej sugestii? –

+0

Życzymy, aby to było prawdą.Właściwie Hibernacja jest obecnie uruchamiany jako pierwszy i jest to problem otwarty. – sofend

+1

@sofend Uważam, że się mylicie i pytanie to również sugeruje. Mamy również testy w Boot, które sprawdzają, czy migracje Flywaya działają przed Hibernate. Co sprawia, że ​​myślisz, że Hibernate działa jako pierwszy? –

6

Miałem ten sam problem.

Chciałem, aby mój schemat był tworzony przez hibernację z powodu jego niezależności od bazy danych. Już miałem kłopot z ustaleniem ładnego schematu dla mojej aplikacji na moich zajęciach jpa, nie lubię się powtarzać.

Ale chcę, aby inicjalizacja danych została wykonana w sposób wersjonowany, w którym jest dobra droga.

Spring boot uruchamia migracje w locie przed hibernacją. Aby to zmienić przeważyłem inicjator rozruchu sprężyny, aby nic nie robić. Następnie utworzyłem drugi inicjator, który działa po hibernacji. Wszystko, co musisz zrobić, to dodać do tej klasy konfiguracji:

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); 
    } 


} 

Ten kod wymaga Javy 8, Jeśli masz Java 7 lub wcześniej, wymienić (f)->{} z wewnętrznym klasy implementującej FlywayMigrationStrategy

oczywiście można zrobić to w formacie xml równie łatwo.

Upewnij się, aby dodać do swoich application.properties:

flyway.baselineOnMigrate = true 
+1

Działa to świetnie. Zamiast @DependsOn wolę po prostu zadeklarować parametr (wtedy jest on mocno napisany), ale to nadpisanie inicjalizacji flywaya jest niezwykle użyteczne. Dzięki! –

+0

Fajnie, ale spróbowałem i nie mogę zlokalizować mojego autorstwa członka. – djangofan

+0

Czy dodałeś wiosenne dane jpa do swojego pom.xml? sprawdź, co robi automatyczna konfiguracja. Lub jak Paul Hilliar powiedział wstrzyknąć to po typie – user3707816