2011-12-15 5 views
30

Bir demo sunucusunda uygulamamın yeni bir sürümünü kuruyorum ve veritabanını günlük olarak sıfırlamanın bir yolunu bulmayı çok istiyorum. Sanırım her zaman bir cron işi bırakma işlemini gerçekleştirebilir ve sorguları oluşturabilirim ama daha temiz bir yaklaşım arıyorum. Damla oluşturma yaklaşımıyla özel bir kalıcılık birimi kullanmayı denedim, ancak sistem sık sık (isteğe bağlı olarak) sunucudan bağlanır ve bağlantıyı keserken çalışmaz.Periyodik olarak Embedded H2 veritabanını sıfırlayın

Daha iyi bir yaklaşım var mı?

cevap

55

H2 drop all objects için özel bir SQL deyimi destekler:

+0

Teşekkür Bunu uygularken – javydreamercsw

+1

TRUNCATE TABLE OTO_INCREMENT sayaçlarını sıfırlamaz :( – Nazar

+2

@Nazar, evet, bu diğer veritabanlarıyla aynı davranıştır, örneğin PostgreSQL ('serial' kullanarak) .Bu doğru davranış olduğunu düşünüyorum. Değerler diğer tablolarda kullanılabilir –

1

komut: tüm masaları düşmesi istemiyorsanız

DROP ALL OBJECTS [DELETE FILES] 

, sen truncate table kullanmak isteyebilirsiniz KAPATMA
RunScript.execute (jdbc_url, kullanıcı, parola, "classpath: shutdown.sql", "UTF8", false) kullanarak çalıştırabilirsiniz;
testlerin Suite bu cevap, aşağıda benim çözüm sonrası "H2 veritabanı reset" için ilk Google sonucudur gibi @AfterClass

12

ile bittiğinde ben her zaman çalıştırabilirim:

her sonra JUnit @tests:

  • devre dışı bırak bütünlük kısıtlaması
  • listesi (varsayılan) tüm tabloları KAMU şema
  • Truncate Tüm masalar
  • listesi (varsayılan) tüm diziler KAMU şema
  • Sıfırlama tüm diziler
  • Reenable kısıtlamaları.

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

diğer çözüm, her bir test başında veritabanı recreatethe olacaktır. Ama bu büyük DB durumunda çok uzun olabilir. ünite, bu örnekte

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

test içinde

+0

bu çok iyi çalışıyor, teşekkürler – aliopi

1

Thre (tüm gerekli tabloları kullanım amacı yerde) biz her test yöntemi sonra drop_all.sql komut yürütme veritabanı manipülasyonu için Spring özel sözdizimi. Biz önce her test yöntemi gerekli tüm tabloları init nereye Bu örnekte biz ( komut init.sql create.sql (biz gerekli tüm tablolar oluşturmak) senaryo ve yürütün.. ben çalışıyorum