【问题标题】:Spring test with H2 in memory database truncate all tables在内存数据库中使用 H2 进行 Spring 测试截断所有表
【发布时间】:2016-12-24 01:42:38
【问题描述】:

我是一名初级 CS 专业学生,正在使用 Spring 进行 MVC 项目,我对 Spring 还很陌生。

我在内存数据库中设置了一个H2并编写了2个sql脚本;一个用于填充数据库,另一个用于将其清空。

据我所知,truncate table <table name>delete from <table name> 之间的实际区别是截断表是 ddl,因此它更快,并且它还重置自动递增的列。问题是 H2 的 truncate table 不会重置自动递增的列。你能指出我在哪里搞砸了吗?

我正在使用 spring 的 SqlGroup 注解来运行脚本。

@SqlGroup({
    @Sql(executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, scripts = 
                                                "classpath:populate.sql"),
    @Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts = 
                                                  "classpath:cleanup.sql")
})

这是应该截断每个表的 cleanup.sql。

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE TABLE `criteria`;
TRUNCATE TABLE `job_title`;
TRUNCATE TABLE `organization`;
TRUNCATE TABLE `organization_teams`;
TRUNCATE TABLE `organization_users`;
TRUNCATE TABLE `organization_job_titles`;
TRUNCATE TABLE `review`;
TRUNCATE TABLE `review_evaluation`;
TRUNCATE TABLE `team`;
TRUNCATE TABLE `team_members`;
TRUNCATE TABLE `user`;
TRUNCATE TABLE `user_criteria_list`;

SET FOREIGN_KEY_CHECKS=1;

并且 populate.sql 只是在不违反完整性约束的情况下向这些表中插入一堆行。

所以当我运行我的测试类时,只有第一个方法通过。其余的我得到这样的东西:

参照完整性约束违规:“FK3MAB5XYC980PSHDJ3JJ6XNMMT:PUBLIC.ORGANIZATION_JOB_TITLES FOREIGN KEY(JOB_TITLES_ID) REFERENCES PUBLIC.JOB_TITLE(ID) (1)”; SQL 语句: 插入organization_job_titles(organization_id, job_titles_id) VALUES(1, 1)

我认为问题出在自动递增的列没有被重置。所以我写了一个不同的测试类:

monAutoIncTest.java

 @Sql(executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD, scripts =
    "classpath:truncateTable.sql")
    public class monAutoIncTest {
        @Autowired
        OrganizationService organizationService;

        @Test
            public void h2truncate_pls() throws BaseException {
            organizationService.add(new Organization("Doogle"));
            Organization fetched = organizationService.getByName("Doogle");
            Assert.assertEquals(1, fetched.getId());
        }

        @Test
        public void h2truncate_plz() throws BaseException {
            organizationService.add(new Organization("Zoogle"));
            Organization fetched = organizationService.getByName("Zoogle");
            Assert.assertEquals(1, fetched.getId());
        }
    } 

使用 truncateTable.sql

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE TABLE `organization`;

SET FOREIGN_KEY_CHECKS=1;

当测试运行时,先运行的方法通过,另一个给我这个。

java.lang.AssertionError: 预期:1 实际:2

【问题讨论】:

    标签: java mysql spring spring-mvc h2


    【解决方案1】:

    为每个表名执行 SQL 脚本:

    TRUNCATE TABLE my_table RESTART IDENTITY;
    ALTER SEQUENCE my_table_id_seq RESTART WITH 1;
    

    H2 应该是 1.4.200 或更高版本。

    https://www.h2database.com/html/commands.html

    【讨论】:

      【解决方案2】:

      目前H2不支持该功能,但我们可以在their roadmap看到这样的计划

      TRUNCATE 应该像在 MySQL 和 MS SQL 中一样重置标识列 服务器(可能还有其他数据库)。

      尝试将此语句与TRUNCATE 组合使用:

      ALTER TABLE [table] ALTER COLUMN [column] RESTART WITH [initial value]
      

      【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-17
      • 2020-03-20
      • 2019-02-02
      • 1970-01-01
      • 2019-11-27
      • 2019-04-01
      • 2018-09-12
      • 2019-03-03
      相关资源
      最近更新 更多