it-swarm.com.de

Setzen Sie die Embedded H2-Datenbank regelmäßig zurück

Ich richte eine neue Version meiner Anwendung in einem Demo-Server ein und würde gerne einen Weg finden, die Datenbank täglich zurückzusetzen. Ich denke, ich kann immer einen Cron-Job ausführen, der Abfragen und Abfragen erstellt, aber ich suche nach einem saubereren Ansatz. Ich habe versucht, eine spezielle Persistenzeinheit mit Drop-Create-Ansatz zu verwenden. Dies funktioniert jedoch nicht, da sich das System häufig (bei Bedarf) mit dem Server verbindet und trennt.

Gibt es einen besseren Ansatz?

38
javydreamercsw

H2 unterstützt eine spezielle SQL-Anweisung, um alle Objekte zu löschen :

DROP ALL OBJECTS [DELETE FILES]

Wenn Sie nicht alle Tabellen löschen möchten, können Sie truncate table verwenden:

TRUNCATE TABLE 
65
Thomas Mueller

Da diese Antwort das erste Google-Ergebnis für "Reset H2 database" ist, poste ich meine Lösung unten: 

Nach jedem JUnit @tests :

  • Deaktivieren Sie die Integritätsbedingung
  • Listet alle Tabellen im (Standard-) PUBLIC-Schema auf
  • Alle Tabellen abschneiden
  • Listen Sie alle Sequenzen im (Standard-) PUBLIC-Schema auf
  • Alle Sequenzen zurücksetzen
  • Aktivieren Sie die Einschränkungen erneut.

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

Die andere Lösung wäre, die Datenbank zu Beginn jedes Tests neu zu erstellen. Bei großen DBs könnte dies jedoch zu lang sein.

19
Nils Renaud

In Spring ist dies eine spezielle Syntax für die Datenbankmanipulation innerhalb von Komponententests

@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 {}

In diesem Beispiel führen wir drop_all.sql script aus (wobei alle erforderlichen Tabellen abgelegt werden) after jede Testmethode ..__ In diesem Beispiel führen wir create.sql script aus (wo wir erstellen) alle erforderlichen Tabellen) und init.sql script (wobei wir alle erforderlichen Tabellen before jeder Testmethode initiieren.

2
oleg.cherednik

Der Befehl: SHUTDOWN
Sie können es mit RunScript.execute ausführen (jdbc_url, Benutzer, Kennwort, "Klassenpfad: shutdown.sql", "UTF8", false);
Ich führe es jedes Mal aus, wenn die Testsuite mit @AfterClass beendet ist

2
dsantaolalla

Wenn Sie Federstiefel verwenden, sehen Sie diese stackoverflow-Frage

  1. Richten Sie Ihre Datenquelle ein. Ich habe keine besondere Schließung bei der Ausfahrt. 

    datenquelle: driverClassName: org.h2.Driver url: "jdbc: h2: mem: psptrx"

  2. Spring Boot @DirtiesContext-Anmerkung

    @DirtiesContext (classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

  3. Verwenden Sie @Before, um jeden Testfall zu initialisieren. 

Der @DirtiesContext bewirkt, dass der h2-Kontext zwischen den einzelnen Tests gelöscht wird.

1
Interlated

sie können den folgenden Code in die Datei application.properties schreiben, um Ihre von JPA geladenen Tabellen zurückzusetzen:

spring.jpa.hibernate.ddl-auto=create
0