我有一些由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
添加到数据库约束中。要进行验证,您可以配置JPA以生成ddl文件。看看ddl
文件,你会注意到ON DELETE CASCADE
不是约束的一部分。将ON DELETE CASCADE
添加到ddl
文件中的实际SQL,然后从ddl更新数据库模式。这将解决您的问题。
这个link展示了如何在MySQL中使用ON DELETE CASCADE
来获取CONSTRAINT
。您可以在约束上执行此操作。您也可以在CREATE TABLE
或ALTER TABLE
声明中执行此操作。 JPA可能会在ALTER TABLE
语句中创建约束。只需将ON DELETE CASCADE
添加到该声明中即可。
请注意,某些JPA实现者确实提供了此功能的方法。
Hibernate使用@OnDelete
注释提供此功能,因此如果您希望坚持使用标准JPA功能,则首选使用此功能或仅更新ddl文件。
我看到两个潜在的问题:
可能还有一些其他情况在某些情况下可能会出现问题,因此我建议不要这样做。
删除父记录时,可以使用本机数据库功能删除子记录。
注意双向关系,并确保您只需指定级联插入和更新(更安全的一面)。
你提到测试目的。我猜测,执行一些测试,删除数据,重播测试......
使用二级缓存或查询缓存时,如果直接从数据库中删除数据,缓存将会过时。这可能会导致意外的测试结果。
所以是的,如果您使用二级/查询缓存,这将与Hibernate冲突,因为实体不会从缓存中逐出。确保在直接删除任何数据后清除所有缓存。 See this question on how to clear cache.
官方的Hibernate docs也提到了这个:
请注意,缓存不知道其他应用程序对持久性存储所做的更改。但是,它们可以配置为定期使缓存的数据到期。
在orphanRemoval = true
关系中使用@OneToMany
子句。然后,当主实体(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<Parameter> 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 Documentation here
因为你的db可能会被破坏。您可以使用正式订单。删除子稳定,然后删除主表