2011-12-15 3 views
30

Sto configurando una nuova versione della mia applicazione in un server demo e mi piacerebbe trovare un modo per reimpostare il database ogni giorno. Suppongo che possa sempre avere un cron job in esecuzione drop e creare query, ma sto cercando un approccio più pulito. Ho provato a utilizzare un'unità di persistenza speciale con approccio drop-create ma non funziona in quanto il sistema si connette e disconnette dal server frequentemente (su richiesta).Ripristina periodicamente il database Embedded H2

C'è un approccio migliore?

risposta

55

H2 supporta una dichiarazione speciale SQL per drop all objects:

DROP ALL OBJECTS [DELETE FILES] 

Se non si vuole far cadere tutte le tabelle, si potrebbe desiderare di utilizzare truncate table:

+0

Grazie. Sto lavorando per l'implementazione di questo: – javydreamercsw

+1

TRUNCATE TABLE non azzera i contatori AUTO_INCREMENT a zero :( – Nazar

+2

@Nazar, sì, questo è lo stesso comportamento degli altri database, ad esempio PostgreSQL (usando 'seriale'). Penso che sia il comportamento corretto, come i valori potrebbero essere utilizzati in altre tabelle –

1

Il comando: shutdown
È possibile eseguirlo utilizzando RunScript.execute (jdbc_url, utente, password, "classpath: shutdown.sql", "UTF8", false);
Io eseguo ogni momento in cui la suite di test è terminato con @AfterClass

12

Poiché questa risposta è il primo risultato di Google per "ripristinare database di H2", ho posto la mia soluzione qui di seguito:

Dopo ogni @tests JUnit:

  • vincolo di integrità Disabilita
  • Lista tutte le tabelle del (default) schema pubblico
  • Tronca Tutte le tabelle
  • Lista tutte le sequenze del (default) schema pubblico
  • Ripristina tutte le sequenze
  • riattivare i vincoli.

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

L'altra soluzione sarebbe quella di recreatethe database al inizio di ogni test. Ma potrebbe essere troppo lungo in caso di DB grande.

+0

funziona molto bene, grazie – aliopi

1

Thre è sintassi speciale a molla per la manipolazione database tra unità test

@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 questo esempio eseguiamo drop_all.sql edizione (dove dropp tutte le tabelle richieste) dopo ogni metodo di prova. In questo esempio eseguiamo create.sql sceneggiatura (dove creiamo tutte le tabelle necessarie) e init.sql sceneggiatura (dove abbiamo INIT prima ogni metodo di prova, tutte le tabelle necessarie.