Réinitialiser périodiquement la base de données H2 intégrée

je mets en place une nouvelle version de mon application dans un serveur de démonstration et j'aimerais trouver un moyen de réinitialiser la base de données quotidiennement. Je suppose que je peux toujours avoir un travail cron exécutant drop et créer des requêtes mais je cherche une approche plus propre. J'ai essayé d'utiliser une unité de persistance spéciale avec une approche drop-create mais cela ne fonctionne pas car le système se connecte et se déconnecte fréquemment du serveur (sur demande).

y a-t-il une meilleure approche?

35
demandé sur TJD 2011-12-15 20:33:20

6 réponses

H2 supporte une déclaration SQL spéciale à drop tous les objets :

DROP ALL OBJECTS [DELETE FILES]

si vous ne voulez pas supprimer toutes les tables, vous pouvez utiliser table tronquée :

TRUNCATE TABLE 
62
répondu Thomas Mueller 2011-12-15 20:21:24

comme cette réponse est le premier résultat Google pour "réinitialiser la base de données H2", je poste ma solution ci-dessous:

après chaque essai :

  • Désactiver la contrainte d'intégrité
  • Liste de toutes les tables dans l' (valeur par défaut) PUBLIC schéma
  • tronquer toutes les tables
  • Liste de toutes les séquences dans l' (valeur par défaut) PUBLIC schéma
  • réinitialiser tous séquences
  • Réactiver les contraintes.

    @After
    public void tearDown() {
        try {
            clearDatabase();
        } catch (Exception e) {
            Fail.fail(e.getMessage());
        }
    }
    
    public void clearDatabase() throws SQLException {
        Connection c = datasource.getConnection();
        Statement s = c.createStatement();
    
        // Disable FK
        s.execute("SET REFERENTIAL_INTEGRITY FALSE");
    
        // Find all tables and truncate them
        Set<String> tables = new HashSet<String>();
        ResultSet rs = s.executeQuery("SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES  where TABLE_SCHEMA='PUBLIC'");
        while (rs.next()) {
            tables.add(rs.getString(1));
        }
        rs.close();
        for (String table : tables) {
            s.executeUpdate("TRUNCATE TABLE " + table);
        }
    
        // Idem for sequences
        Set<String> sequences = new HashSet<String>();
        rs = s.executeQuery("SELECT SEQUENCE_NAME FROM INFORMATION_SCHEMA.SEQUENCES WHERE SEQUENCE_SCHEMA='PUBLIC'");
        while (rs.next()) {
            sequences.add(rs.getString(1));
        }
        rs.close();
        for (String seq : sequences) {
            s.executeUpdate("ALTER SEQUENCE " + seq + " RESTART WITH 1");
        }
    
        // Enable FK
        s.execute("SET REFERENTIAL_INTEGRITY TRUE");
        s.close();
        c.close();
    }
    

l'autre solution serait de retraiter la base de données au début de chaque test. Mais ça pourrait être trop long en cas de Grosse maladie.

18
répondu Nils Renaud 2018-03-29 11:28:49

la commande: SHUTDOWN

Vous pouvez l'exécuter en utilisant RunScript.exécuter (jdbc_url, utilisateur, mot de passe, "classpath:shutdown.sql", "UTF8", false);

Je l'exécute chaque fois que la Suite de tests est terminée en utilisant @AfterClass

2
répondu dsantaolalla 2013-03-19 12:59:15

est une syntaxe spéciale au printemps pour la manipulation de base de données dans les tests unitaires

@Sql(scripts = "classpath:drop_all.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD)
@Sql(scripts = {"classpath:create.sql", "classpath:init.sql"}, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
public class UnitTest {}

dans cet exemple, nous exécutons drop_all.sql script (où nous dropp toutes les tables requises) après chaque méthode d'essai. Dans cet exemple, nous exécutons créer.sql script (où nous créons toutes les tables nécessaires) et init.sql script (où nous init toutes les tables nécessaires avant , chaque méthode d'essai.

2
répondu oleg.cherednik 2017-04-07 21:28:58

si vous utilisez une botte à ressort, voir cette question sur l'empilage

  1. configurez votre source de données. Je n'ai pas de fermeture spéciale à la sortie.

    source de données: driverClassName: org.h2.Pilote url: "jdbc: h2: mem: psptrx "

  2. Spring boot @DirtiesContext annotation

    @DirtiesContext (classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

  3. utiliser " avant d'initialiser sur chaque cas d'essai.

le contexte @Dirtiescon entraînera l'abandon du contexte h2 entre chaque test.

1
répondu Interlated 2018-04-03 23:52:57

, vous pouvez écrire dans l'application.propriétés le code suivant pour réinitialiser vos tables qui sont chargées par JPA:

spring.jpa.hibernate.ddl-auto=create
0
répondu Mohamad Alesmaeil 2018-07-21 17:09:19