19

我有一些由 Hibernate 管理的具有各种外键约束的表。Cascade on delete 目前由 Hibernate 单独管理。为了玩弄测试数据,我经常手动创建和删除一些行。如果我可以将 ON DELETE CASCADE 添加到外键约束中,这将对我有很大帮助,但我不知道 Hibernate 是否会遇到这个问题,因为数据库在 Hibernate 之前删除了一些东西。


很多人似乎都专注于 DDL。我的意图不是指示 Hibernate 使用 SQL DELETE CASCADE 创建 DDL。我只想知道如果我在数据库cascade = CascadeType.REMOVE指定一个 ON DELETE CASCADE 以及在参考注释上使用 JPA是否会造成任何伤害,例如@ManyToOne.

4

7 回答 7

5

您可以使用CascadeType.DELETE,但是此注释仅适用于 中的对象EntityManager,而不适用于数据库。您要确保将ON DELETE CASCADE其添加到数据库约束中。要进行验证,您可以配置 JPA 以生成 ddl 文件。查看ddl文件,您会注意到它ON DELETE CASCADE不是约束的一部分。添加ON DELETE CASCADEddl文件中的实际 SQL,然后从 ddl 更新您的数据库架构。这将解决您的问题。

链接显示如何在 MySQL中使用ON DELETE CASCADEon 。CONSTRAINT您在约束上执行此操作。您也可以在CREATE TABLEorALTER TABLE语句中执行此操作。JPA 很可能在ALTER TABLE语句中创建了约束。只需添加ON DELETE CASCADE到该声明。

请注意,一些 JPA 实现者确实为此功能提供了一种方法。

Hibernate 确实使用@OnDelete注释提供了此功能,因此如果您想坚持使用标准 JPA 功能,最好使用此功能或简单地更新 ddl 文件。

于 2013-10-30T17:17:30.257 回答
2

我看到两个潜在的问题:

  1. 如果表示您直接在数据库中级联操作的表的实体是版本化的,那么它将不起作用,因为当 Hibernate 尝试自行删除记录时,版本检查将失败(Hibernate 会假设并发线程已经更新或删除相应的记录)。
  2. 如果在某些用例中,您的业务逻辑在将此类实体实例从父级级联到它们之后重新保留它们(例如,您正在删除旧的父级并将关联的子级迁移到新的父级,尽管为了更清楚我会如果关联存在这样的用例,则根本不会级联删除,但这取决于您,因为它是 JPA 规范所允许的),那么 Hibernate 只会取消删除子级的计划并仅删除父级,所以你会如果您在数据库中级联删除,最终仍会删除子项。

可能还有其他一些情况在某些情况下可能会出现问题,所以我建议要这样做。

于 2018-03-01T21:05:35.380 回答
0

您可以使用本机数据库功能在删除父记录时删除子记录。

请注意双向关系,并确保您只在级联中指定插入和更新(为了更安全)。

于 2013-10-30T18:08:37.540 回答
0

ON DELETE CASCADE只要您没有CascadeType.REMOVEorphanRemoval启用以防止实体移除事件的传播,您就可以安全地使用。

拥有@OnDelete(action = OnDeleteAction.CASCADE)你的关系将迫使 HibernateON DELETE CASCADE为相关的外键生成。但是,您必须通过返回方法Dialect来表明这种关系是受支持的truesupportsCascadeDelete

Dialect.supportsCascadeDelete()

删除

于 2020-05-18T13:14:16.727 回答
0

您出于测试目的提及。我猜,执行一些测试,删除数据,重放测试......

当使用二级缓存或查询缓存时,如果您直接从数据库中删除数据,缓存将会过时。这可能会导致意外的测试结果。

所以是的,如果您使用二级/查询缓存,这将与 Hibernate 冲突,因为实体不会从缓存中被逐出。确保在直接删除任何数据后清除所有缓存。有关如何清除缓存,请参阅此问题。

官方的 Hibernate文档也提到了这一点:

请注意,缓存不知道其他应用程序对持久存储所做的更改。但是,它们可以配置为定期使缓存数据过期。

于 2018-03-01T14:21:16.027 回答
0

从我的实验来看,由于我已经为此苦苦挣扎了几个小时,updatable = false所以在 @JoinColumn 中使用会阻止 Hibernate

update theTable set theReference = null where theIdentifier = ?

例如(在 Kotlin 中):

@Entity
@Table(name = "course")
class Course(
    @Column(name = "title")
    var title: String? = null,
    @OneToMany(cascade = [CascadeType.PERSIST])
    @JoinColumn(name = "course_id", updatable = false)
    val reviews: MutableList<Review> = mutableListOf()
) {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    var id: Int? = null

}
于 2022-01-19T20:46:25.597 回答
-1

不要在这里使用 cascade = CascadeType.REMOVE 文档

因为你的数据库可能会被破坏。您可以使用正式订单。删除子稳定,然后删除主表

于 2018-02-27T17:56:45.230 回答