web-dev-qa-db-ja.com

埋め込みH2データベースを定期的にリセットする

デモサーバーでアプリケーションの新しいバージョンを設定していますが、毎日データベースをリセットする方法を見つけたいと思っています。ドロップとクエリの作成を実行するcronジョブをいつでも実行できると思いますが、よりクリーンなアプローチを探しています。ドロップ作成アプローチで特別な永続性ユニットを使用しようとしましたが、システムがサーバーに頻繁に接続および切断するため(オンデマンドで)機能しません。

より良いアプローチはありますか?

40
javydreamercsw

H2は、 すべてのオブジェクトをドロップ :への特別なSQLステートメントをサポートしています。

DROP ALL OBJECTS [DELETE FILES]

すべてのテーブルを削除したくない場合は、 truncate table を使用できます。

TRUNCATE TABLE 
70
Thomas Mueller

この応答は「H2データベースのリセット」の最初のGoogle結果であるため、以下にソリューションを投稿します。

各JUnit @testsの後

  • 整合性制約を無効にする
  • (デフォルト)PUBLICスキーマ内のすべてのテーブルをリストする
  • すべてのテーブルを切り捨てる
  • (デフォルト)PUBLICスキーマ内のすべてのシーケンスをリストする
  • すべてのシーケンスをリセット
  • 制約を再度有効にします。

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

他の解決策は、各テストの開始時にデータベースを再作成することです。ただし、大きなDBの場合は長すぎる可能性があります。

20
Nils Renaud

コマンド:SHUTDOWN
RunScript.execute(jdbc_url、user、password、 "classpath:shutdown.sql"、 "UTF8"、false);を使用して実行できます。
@ AfterClassを使用して一連のテストが終了するたびに実行します

3
dsantaolalla

Threは、単体テスト内のデータベース操作のためのSpringの特別な構文です

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

この例では、drop_all.sql script(必要なすべてのテーブルをドロップする)afterすべてのテストメソッドを実行します。この例では、create.sql script(必要なすべてのテーブルを作成する)およびinit.sql script(必要なすべてのテーブルを初期化するbeforeを実行します=各試験方法。

2
oleg.cherednik

スプリングブートを使用している場合は、これを参照してください stackoverflow question

  1. データソースをセットアップします。終了時に特別なクローズはありません。

    データソース:driverClassName:org.h2.Driver url: "jdbc:h2:mem:psptrx"

  2. Spring Boot @DirtiesContextアノテーション

    @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

  3. @Beforeを使用して、各テストケースで初期化します。

@DirtiesContextにより、各テストの間にh2コンテキストがドロップされます。

2
Interlated

application.propertiesに次のコードを記述して、JPAによってロードされたテーブルをリセットできます。

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