我可以在Hibernate管理的表中添加“ON DELETE CASCADE”吗?

我有一些由Hibernate管理的表,有各种外键约束。 Cascade on delete目前仅由Hibernate管理。 为了解决测试数据,我经常手动创建和删除一些行。 如果我可以将ON DELETE CASCADE添加到外键约束中,那将对我有很大帮助,但我不知道Hibernate是否因为数据库在Hibernate之前移除了东西而绊倒了。


很多人似乎都专注于DDL。 我的目的不是指示Hibernate使用SQL DELETE CASCADES创建DDL。 我只是想知道如果我在数据库指定ON DELETE CASCADE 除了在参考注释上具有JPA的cascade = CascadeType.REMOVE (例如@ManyToOne 之外是否有任何伤害。

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

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

请注意,某些JPA实现程序确实提供了此function的方法。

Hibernate使用@OnDelete注释提供此function,因此如果您希望坚持使用标准JPAfunction,则首选使用此function或仅更新ddl文件。

我看到两个潜在的问题:

  1. 如果一个实体表示你在数据库中直接级联操作的表是版本化的,那么它将无法工作,因为当Hibernate试图自己删除记录时,版本检查会失败(Hibernate会假设并发线程已经更新或删除)相应的记录)。
  2. 如果有一些用例,您的业务逻辑会重新保留这些实体实例,这些实体实例在移除后已从父级转换为它们(例如,您正在删除旧的父级并将关联的子级迁移到新的父级,尽管为了更清晰,我会如果对于关联存在这样的用例,则根本不进行级联删除,但这取决于您,因为JPA规范允许),然后Hibernate将仅取消安排删除子项并仅删除父项,因此您将如果在数据库中级联删除,仍然会删除已删除的子项。

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

删除父记录时,可以使用本机数据库function删除子记录。

注意双向关系,并确保您只需指定级联插入和更新(更安全的一面)。

你提到测试目的。 我猜测,执行一些测试,删除数据,重播测试……

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

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

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

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

@OneToMany关系中使用orphanRemoval = true子句。 然后,当主实体(ParameterGroup)被删除时,每个相关记录(参数)将首先被删除。 只需通过entityManager删除ParameterGroup实体。 还记得将cascade子句设置为CascadeType.ALL (支持所有级联操作)或CascadeType.REMOVE (仅支持级联删除)。

 @Entity @Table(name = "PARAMETER_GROUP") public class ParameterGroup { @Id private Long id; @OneToMany(mappedBy = "parameterGroup", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) private List parameters = new LinkedList<>(); } @Entity @Table(name = "PARAMETER") public class Parameter { @Id private Long id; @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH) @JoinColumn(name = "PARAMETER_GROUP_ID") private ParameterGroup parameterGroup; } 

从文档:

public abstract boolean orphanRemoval (Optional)

是否将删除操作应用于已从关系中删除的实体,并将删除操作级联到这些实体。

不要在此处使用cascade = CascadeType.REMOVE 文档

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