Hibernate H2 指定删除表顺序

Posted

技术标签:

【中文标题】Hibernate H2 指定删除表顺序【英文标题】:Hibernate H2 specify drop table order 【发布时间】:2020-04-21 00:18:38 【问题描述】:

我也有类似this user 的问题。 Hibernate 无法在每次 SpringBootTest 之后删除我的内存测试数据库的表(例如,在运行 mvn 测试时)。期望的行为是ddl-auto=create-drop,但这不起作用。

我认为原因可能是 DROP TABLE 语句的顺序无效,因此 Hibernate 会尝试删除其他表仍依赖的表。

我的 data.sql 脚本仅包含 INSERT 语句,并且架构是根据我的实体自动创建的。我尝试将DROP TABLE 语句添加到data.sql 的顶部并且它们都通过了(ddl-auto=create),因为我可以指定它们必须被删除的顺序。 另一方面,我现在也必须在 data.sql 中指定模式创建..

有没有一种方法可以指定 drop 语句的顺序,而不必指定模式创建?或者有人知道initial problem 的解决方案吗?

编辑:

我想举个例子。我有一个与其他实体(M:N、1:N、1:1)有关系的User 实体。创建模式时,hibernate 会删除所有表,创建它们并添加约束:

// first test file:
Hibernate: drop table user if exists
... // drop other tables
Hibernate: create table user (username varchar(255) not null, ... , primary key (username))
... // create other tables
Hibernate: alter table X add constraint FKgi38hy0tsrdm332gdjrc0uhm3 foreign key (username) references user
Hibernate: alter table Y add constraint FK5svpy1b71l4jxni0xylrbbdtv foreign key (username) references user
Hibernate: alter table Z add constraint FK5a8fxbb0ug3eo1lisdrrxbbj foreign key (username) references user

// next test file:
Caused by: org.h2.jdbc.JdbcSQLSyntaxErrorException: Cannot drop "USER" because "FKGI38HY0TSRDM332GDJRC0UHM3, FK5SVPY1B71L4JXNI0XYLRBBDTV, FK5A8FXBB0UG3EO1LISDRRXBBJ" depends on it; SQL statement:
drop table user if exists [90107-200]

这个过程在第一个测试文件之后不起作用,因为它违反了约束。这就是我想指定放置顺序的原因。

我没有在我的实体上使用 CascadeType,这会导致问题吗?

【问题讨论】:

你能展示你的映射和drop语句吗? 你真的想要我所有实体的代码吗? 首先发布 drop 语句并告诉我们它在哪个 drop 上失败。那我们看看是不是映射有问题 如果我手动指定 drop 语句,它们不会失败。如果我的 data.sql 仅包含插入语句,它将失败。但是 Hibernate 应该在每次测试后删除表,因为我使用 create-drop。这不起作用(链接问题中的错误) @SimonMartinelli 看来并非如此。不适用于 replace=none 选项和 springboot 2.2.2。和 2.0.4 一样,但是有了这个选项,springboot 2.2.2 db 只被初始化一次,没有被删除,并且下一个测试文件的初始化失败。 【参考方案1】:

您必须使用 DirtiesContext 注释您的测试类:

@DirtiesContext(methodMode = MethodMode.BEFORE_CLASS)

这将重建测试上下文,因此也会创建-删除您的架构。

阅读更多信息:https://www.baeldung.com/spring-dirtiescontext

【讨论】:

我认为您的意思是ClassMode.BEFORE_CLASS,但这并不能解决我的问题。是的,它触发了数据库模式的删除,但这又引发了链接问题的描述错误 在 spring-boot 2.2.2 中使用 replace=none 这也无济于事。我不知道 2.0.4 和 2.2.2 之间发生了什么变化,我想控制它,但我不知道该怎么做,也无法在任何地方找到答案。如果您知道如何在每个测试文件(在我的情况下为 @DataJpaTest)之后强制 wpring 重新初始化 db,即使 replace=none 已到位,请提供帮助。我没有成长为 replace=none,但我无法做的另一件事是强制自动配置的数据源创建模式:(【参考方案2】:

我终于找到了解决我的问题的方法。 正如我所说,由于尝试删除其他表仍然依赖的表而导致的错误。我认为这可能与缺少 CascadeType 规范有关,但我无法修复它。

然后我找到了this answer,它对我有用。除了我的data.sql 文件(我的所有数据都插入到自动创建的模式中)之外,我现在有一个drop-tables.sql,我可以在其中指定DROP 语句的正确顺序。该文件在自动创建模式之前执行,因此解决了我的问题。

application.properties:

spring.jpa.properties.javax.persistence.schema-generation.database.action=drop-and-create
spring.jpa.properties.javax.persistence.schema-generation.drop-source=script-then-metadata
spring.jpa.properties.javax.persistence.schema-generation.drop-script-source=drop-tables.sql

【讨论】:

它对我不起作用。我找到了适合我的解决方案***.com/a/60012915/607637。让我知道这是否适合您。

以上是关于Hibernate H2 指定删除表顺序的主要内容,如果未能解决你的问题,请参考以下文章

数据结构从零实现顺序表+链表相关操作

hibernate删除表的方法

数据结构--顺序表简单实现(总结)

Hibernate/H2 @OneToMany 删除子时“违反参照完整性约束”?

JPA/Hibernate - 删除子删除父(从同一个表)

线性表之顺序存储-顺序表