J'ai créé l'application Spring. Pom xml est joint.
Il a une configuration comme celle-ci (ci-dessous) et un outil de migration db/migration/V1__init.sql pour Flyway db.
Il a une base de données en mémoire hsqldb et il est créé après le démarrage de l'application. Il est propre après sa création.
Je veux qu'Hibernate crée un schéma basé sur des classes d'entités, puis Flyway remplit les tables. Flyway démarre maintenant V1__init.sql avant la création des tables et lève une exception. Comment puis-je modifier cette commande ou quelle solution puis-je faire?
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>
J'ai eu le même problème.
Je voulais que mon schéma soit créé par hibernate en raison de l'indépendance de sa base de données. J'ai déjà eu la peine de trouver un schéma sympa pour mon application dans mes cours jpa, je n'aime pas me répéter.
Mais je veux que l'initialisation des données se fasse de manière versionnée, ce que flyway est bon.
Spring boot exécute des migrations de voie de migration avant la mise en veille prolongée. Pour le changer, j'ai annulé l'initialiseur Spring Boot pour ne rien faire. J'ai ensuite créé un deuxième initialiseur qui s'exécute après la mise en veille prolongée. Il vous suffit d'ajouter cette classe de configuration:
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);
}
}
Ce code a besoin de Java 8, si vous avez Java 7 ou antérieur, remplacez (f)->{}
avec une classe interne qui implémente FlywayMigrationStrategy
Bien sûr, vous pouvez le faire aussi facilement en xml.
Assurez-vous d'ajouter ceci à votre application.properties:
flyway.baselineOnMigrate = true
La configuration automatique Spring Boot de Flyway garantit que les migrations de base de données ont été exécutées avant l'initialisation d'Hibernate. En d'autres termes, vous ne pouvez pas compter sur la configuration automatique de Flyway et utiliser Flyway pour remplir les tables créées par Hinernate.
Une solution consiste à adopter pleinement Flyway et à l'utiliser à la fois pour créer les tableaux et les remplir. Vous pouvez ensuite désactiver la création de table d'Hibernate (spring.jpa.hibernate.ddl-auto=none
). Cette approche est plus robuste car elle permettra à votre base de données d'évoluer plus facilement. C'est ce que je recommanderais de faire.
Une autre solution consiste à désactiver la configuration automatique de Flyway (flyway.enabled=false
) et pour le configurer vous-même. Vous pouvez ensuite configurer Flyway pour qu'il dépende d'Hibernate afin qu'Hibernate ait créé les tables avant que Flyway n'essaye de les remplir.
Toutes les migrations SQL commenceront après qu'Hibernate aura créé toutes les tables.
Spring Boot 2.2.2, Flyway 6.0.8
Pour désactiver le démarrage pour Flyway, insérez-le dans resources/application.properties:
spring.flyway.enabled=false
Créez une configuration distincte pour Flyway pour le charger lorsque Hibernate est prêt:
@Configuration
public class FlywayConfiguration {
@Autowired
public FlywayConfiguration(DataSource dataSource) {
Flyway.configure().baselineOnMigrate(true).dataSource(dataSource).load().migrate();
}
}
Démarrez vos scripts de migration à partir de la version 2:
resources/db.migration/V2__fill-tables.sql
V1 est utilisé comme référence, le fichier V1 sera ignoré.
Pour les utilisateurs plus récents qui utilisent Spring Boot +2.1 et comme @mota l'a commenté dans la réponse de @ user3707816, vous pouvez utiliser spring.flyway.enabled = false dans application.properties, puis créer une nouvelle instance manuellement:
Flyway.configure().dataSource(dataSource)
.baselineOnMigrate(true)
.schemas(PG_DATABASE_SCHEMA)//optional, by default is public
.load().migrate();
peut être à cause de la commande
ajouter sur application.properties
flyway.out-of-order = true
ou application.yml au printemps
flyway:
out-of-order: true