定期重置Embedded H2数据库

时间:2011-12-15 16:33:21

标签: reset h2

我在演示服务器中设置了我的应用程序的新版本,并希望找到一种每天重置数据库的方法。我想我总是可以执行一个cron作业执行drop并创建查询,但我正在寻找一种更清洁的方法。我尝试使用具有drop-create方法的特殊持久性单元,但它不起作用,因为系统经常连接和断开服务器(按需)。

有更好的方法吗?

6 个答案:

答案 0 :(得分:68)

H2支持drop all objects的特殊SQL语句:

DROP ALL OBJECTS [DELETE FILES]

如果您不想删除所有表格,可能需要使用truncate table

TRUNCATE TABLE 

答案 1 :(得分:20)

由于此回复是"重置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();
    }
    

另一种解决方案是在每次测试开始时重新创建数据库。但是对于大数据库来说,这可能太长了。

答案 2 :(得分:2)

命令:SHUTDOWN
您可以使用RunScript.execute(jdbc_url,user,password,“classpath:shutdown.sql”,“UTF8”,false)执行它;
每次使用@AfterClass

完成测试套件时,我都会运行它

答案 3 :(得分:2)

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 脚本(我们在所有必需的表中删除)每个测试方法之后。 在这个例子中,我们执行 create.sql 脚本(我们创建所有必需的表)和 init.sql 脚本(我们在之前初始化所有必需的表 >每种测试方法。

答案 4 :(得分:1)

如果您使用的是春季启动,请参阅此stackoverflow question

  1. 设置数据源。退出时我没有特别关闭。

    数据源:   driverClassName:org.h2.Driver   url:“jdbc:h2:mem:psptrx”

  2. Spring boot @DirtiesContext annotation

    @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

  3. 使用@Before初始化每个测试用例。

  4. @DirtiesContext将导致在每次测试之间删除h2上下文。

答案 5 :(得分:0)

您可以在application.properties中编写以下代码,以重置由JPA加载的表:

spring.jpa.hibernate.ddl-auto=create