2011-12-15 19 views
30

Tôi đang thiết lập phiên bản mới của ứng dụng trong máy chủ demo và rất muốn tìm cách đặt lại cơ sở dữ liệu hàng ngày. Tôi đoán tôi luôn luôn có thể có một công việc cron thực hiện thả và tạo truy vấn nhưng tôi đang tìm kiếm một cách tiếp cận sạch hơn. Tôi đã thử sử dụng một đơn vị kiên trì đặc biệt với cách tiếp cận drop-create nhưng nó không hoạt động khi hệ thống kết nối và ngắt kết nối khỏi máy chủ thường xuyên (theo yêu cầu).Đặt lại cơ sở dữ liệu nhúng H2 theo định kỳ

Có cách tiếp cận nào tốt hơn không?

Trả lời

55

H2 hỗ trợ một câu lệnh SQL đặc biệt để drop all objects:

DROP ALL OBJECTS [DELETE FILES] 

Nếu bạn không muốn thả tất cả các bảng, bạn có thể muốn sử dụng truncate table:

+0

Cảm ơn. Tôi đang làm việc – javydreamercsw

+1

TRUNCATE TABLE không đặt lại các bộ đếm AUTO_INCREMENT thành 0: ( – Nazar

+2

@Nazar, vâng, đây cũng là hành vi tương tự như các cơ sở dữ liệu khác, ví dụ PostgreSQL (sử dụng 'nối tiếp') .Tôi nghĩ đó là hành vi đúng, như các giá trị có thể được sử dụng trong các bảng khác –

1

Lệnh: SHUTDOWN
Bạn có thể thực thi nó bằng cách sử dụng RunScript.execute (jdbc_url, user, password, "classpath: shutdown.sql", "UTF8", false);
tôi chạy nó mỗi khi Suite kiểm tra kết thúc bằng @AfterClass

12

Như phản ứng này là kết quả đầu tiên của Google cho "thiết lập lại cơ sở dữ liệu H2", tôi gửi giải pháp của tôi dưới đây:

Sau mỗi @tests JUnit:

  • Disable vẹn hạn chế
  • Danh sách tất cả các bảng trong (mặc định) schema CÔNG
  • Truncate tất cả các bảng
  • Liệt kê tất cả các chuỗi trong (mặc định) schema CÔNG
  • Thiết lập lại tất cả các chuỗi
  • Kích hoạt lại các khó khăn.

    @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ác giải pháp khác sẽ được recreatethe cơ sở dữ liệu vào lúc bắt đầu của mỗi bài kiểm tra. Nhưng điều đó có thể quá dài trong trường hợp DB lớn.

+0

hoạt động rất tốt, cảm ơn – aliopi

1

Thre là cú pháp đặc biệt trong mùa xuân cho các thao tác cơ sở dữ liệu trong phạm vi đơn vị kiểm tra

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

Trong ví dụ này, chúng tôi thực hiện drop_all.sql kịch bản (nơi chúng tôi dropp tất cả các bảng bắt buộc) sau mỗi phương pháp thử nghiệm. Trong ví dụ này, chúng tôi thực hiện create.sql kịch bản (nơi chúng ta tạo ra tất cả các bảng bắt buộc) và init.sql kịch bản (nơi chúng tôi init tất cả các bảng cần trước mỗi phương pháp thử nghiệm.

Các vấn đề liên quan