【问题标题】:Reset Embedded H2 database periodically定期重置嵌入式 H2 数据库
【发布时间】:2012-01-21 08:17:45
【问题描述】:

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

有更好的方法吗?

【问题讨论】:

    标签: reset h2


    【解决方案1】:

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

    DROP ALL OBJECTS [DELETE FILES]
    

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

    TRUNCATE TABLE 
    

    【讨论】:

    • TRUNCATE TABLE 不会将 AUTO_INCREMENT 计数器重置为零:(
    • @Nazar,是的,这与其他数据库的行为相同,例如 PostgreSQL(使用 serial)。我认为这是正确的行为,因为这些值可能会在其他表中使用。
    • @ThomasMueller - JdbcDataSource ds = new JdbcDataSource(); ds.setURL("jdbc:h2:~/mydb"); ds.setUser("sa"); ds.setPassword("pass");...etc 我用它在我的 eclipse java 项目中创建一个嵌入式数据库。如何删除 db-mydb ?谢谢。
    • @ThomasMueller - 另外,您能告诉我嵌入式数据库在硬盘中的位置吗?我在stackoverflow.com/questions/25587693/… 上提出了一个问题。谢谢。
    【解决方案2】:

    由于此响应是“重置 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();
      }
      

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

    【讨论】:

    • 我在 org.junit.rules.TestRule 中使用它 - 它会在每次测试之前重置数据库。
    • 不错的答案,但序列并不总是从 1 开始。
    【解决方案3】:

    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 脚本(我们在其中初始化所有必需的表 before 每种测试方法。

    【讨论】:

    • 这是我为此类问题找到的最简单直观的解决方案。
    【解决方案4】:

    如果您使用的是 Spring Boot,请参阅此stackoverflow question

    1. 设置您的数据源。我在退出时没有任何特别的关闭。

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

    2. Spring boot @DirtiesContext 注解

      @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)

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

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

    【讨论】:

      【解决方案5】:

      命令:SHUTDOWN
      您可以使用

      执行它

      RunScript.execute(jdbc_url, user, password, "classpath:shutdown.sql", "UTF8", false);

      我每次使用 @AfterClass 完成测试套件时都会运行它

      【讨论】:

        【解决方案6】:

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

        spring.jpa.hibernate.ddl-auto=create
        

        【讨论】:

        • 是的,但这不会处理其他表,例如内部用于自动增量的表。
        猜你喜欢
        • 1970-01-01
        • 2017-03-05
        • 1970-01-01
        • 2016-01-22
        • 2018-05-15
        • 2022-01-20
        • 2012-10-22
        • 2018-06-13
        • 2017-10-06
        相关资源
        最近更新 更多