2016-05-08 19 views
5

Ho creato un'applicazione Spring. Pom xml è allegato.Spring Boot: Hibernate e Flyway Boot Order

Ha un config come questo (sotto) e alcuni db/migration/V1__init.sql per lo strumento di migrazione db Flyway.

Ha un database in memoria hsqldb e viene creato dopo l'avvio dell'applicazione. È pulito dopo la creazione.

Desidero che Hibernate crei uno schema basato sulle classi di entità, quindi Flyway riempie le tabelle. Ora Flyway avvia V1__init.sql prima che le tabelle vengano create e genera un'eccezione. Come posso cambiare questo ordine o quale soluzione posso fare?

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

non collegati alla tua domanda, ma si dovrebbe rimuovere molte delle versioni dal vostro pom e lasciare Boot configurarli per voi. E certamente non dovresti mescolare le versioni di Spring Boot (hai 1.3.2.RELEASE e 1.3.3.RELEASE). –

risposta

1

ho risolto il mio compito. Ho rimosso Flyway e ho appena aggiunto data.sql

8

Spring Boot con la configurazione automatica di Flyway assicura che le migrazioni del database siano eseguite prima dell'inizio di Hibernate. In altre parole, non è possibile fare affidamento sulla configurazione automatica di Flyway e utilizzare Flyway per popolare le tabelle create da Hinernate.

Una soluzione è abbracciare completamente Flyway e usarlo sia per creare i tavoli che per popolarli. È quindi possibile disattivare la creazione della tabella di Hibernate (spring.jpa.hibernate.ddl-auto=none). Questo approccio è più solido in quanto consente al database di evolvere più facilmente. Questo è quello che raccomanderei di fare.

Un'altra soluzione è disabilitare l'auto-configurazione di Flyway (flyway.enabled=false) e configurarlo autonomamente. È quindi possibile configurare Flyway in modo che dipenda da Hibernate in modo che Hibernate abbia creato le tabelle prima che Flyway tenti di popolarle.

+1

Hai qualche codice di esempio del tuo secondo suggerimento? –

+0

Ci auguriamo che fosse vero.Attualmente Hibernate viene eseguito per primo e questo è un problema aperto. – sofend

+1

@sofend Credo che tu ti sbagli e anche la domanda lo suggerisce. Abbiamo anche test in avvio che verificano che le migrazioni Flyway vengano eseguite prima di Hibernate. Cosa ti fa pensare che Hibernate funzioni per primo? –

6

Ho avuto lo stesso problema.

Volevo che il mio schema fosse creato da ibernazione a causa della sua indipendenza dal database. Ho già avuto il problema di trovare uno schema per la mia applicazione nelle mie classi jpa, non mi piace ripetermi.

Ma voglio che l'inizializzazione dei dati avvenga in modo versionato su cui è valido il flyway.

L'avvio a molla esegue migrazioni passerelle prima del letargo. Per cambiarlo ho annullato l'inizializzatore di avvio a molla per non fare nulla. Quindi ho creato un secondo inizializzatore che viene eseguito dopo l'ibernazione. Tutto quello che dovete fare è aggiungere questa classe di configurazione:

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


} 

Questo codice ha bisogno di Java 8, se si dispone di Java 7 o versioni precedenti, sostituire (f)->{} con una classe interna che implementa FlywayMigrationStrategy

Naturalmente si può fare questo in xml altrettanto facilmente.

Assicurati di aggiungere questo ai vostri application.properties:

flyway.baselineOnMigrate = true 
+1

Funziona alla grande. Invece di @DependsOn preferisco semplicemente dichiarare un parametro (quindi è fortemente digitato), ma questa sovrascrittura dell'inizializzazione del flyway è estremamente utile. Grazie! –

+0

Bello ma l'ho provato e non è possibile individuare il mio entitymanagerfactory con il suo nome. – djangofan

+0

Hai aggiunto i dati di primavera jpa al tuo pom.xml? controlla cosa sta facendo la configurazione automatica. O come ha detto Paul Hilliar, iniettandolo per tipo – user3707816

Problemi correlati