在Hibernate中删除大型实体的最佳策略

在Hibernate中删除大型实体的最佳策略,hibernate,jpa,entity,one-to-many,Hibernate,Jpa,Entity,One To Many,我有一个父实体,在web应用程序中有许多chilren集合。删除此实体的最佳策略是什么?我可以删除父集合,由于级联,所有子集合都将被删除。但我担心这会花费很长时间,并可能导致表锁定,从而影响其他用户。或者,我可以删除每个子实体,并在最后删除父实体。最好的方法是什么? 一次删除父级和子级。我用这个 entityManger.remove(parent); -> one transaction 或者我可以循环遍历每个子集合,首先删除所有子集合,最后删除父集合。这会将一个大型事务拆分为多个较

我有一个父实体,在web应用程序中有许多chilren集合。删除此实体的最佳策略是什么?我可以删除父集合,由于级联,所有子集合都将被删除。但我担心这会花费很长时间,并可能导致表锁定,从而影响其他用户。或者,我可以删除每个子实体,并在最后删除父实体。最好的方法是什么? 一次删除父级和子级。我用这个

entityManger.remove(parent);  -> one transaction

或者我可以循环遍历每个子集合,首先删除所有子集合,最后删除父集合。这会将一个大型事务拆分为多个较小的事务。

只有在父事务没有子事务时才能执行此操作。在处理父项之前,必须先删除所有子项。

@OneToMany default strategy fetch=FetchType.LAZY

级联键入所有、保留、合并、删除、刷新、分离。

如果要删除包含子项的父项集合。更改父级联={cascadeType.REMOVE和ALL}

您没有定义级联类型。请删除。获取错误(违反了db fk密钥约束)

关系中的孤儿移除 当从关系中删除一对一或一对多关系中的目标实体时,通常需要将删除操作级联到目标实体。这样的目标实体被视为“孤立实体”,并且“孤立移除”属性可用于指定应移除孤立实体。例如,如果订单有多个行项目,并且其中一个已从订单中删除,则删除的行项目将被视为孤立项。如果将删除设置为true,则从订单中删除行项目时将删除行项目实体

@OneToMany和@oneToOne中的孤儿移除属性采用布尔值,默认情况下为false

以下示例将从关系中删除孤立客户实体时,将删除操作级联到该孤立客户实体:

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }
@OneToMany(mappedBy=“customer”,orphan=“true”)
公共列表getOrders(){…}

所有其他答案似乎都不能解决您的问题

首先,除非您要处理大量使用的表或按顺序或数百万次删除,否则您不会面临任何重大的性能问题

但是,如果您确实有上述场景,您可以做几件事(并且您必须在性能或行锁定预防之间进行选择)

1) 确保外键中有索引

2) 按照你说的批量删除。这将防止锁定,但会降低性能,因为应用程序需要向DB调用多个语句。更多信息请点击这里

3) 使用本机SQL查询并执行批删除

DECLARE @RowCount int
WHILE 1=1
    BEGIN
        DELETE TOP (10000) t1
        FROM table t1
        WHERE t1.FK_ID = yourFkId

        SET @RowCount = @@ROWCOUNT

        IF (@RowCount < 10000) BREAK
    END
DECLARE@RowCount int
而1=1
开始
删除顶部(10000)t1
来自表t1
其中t1.FK_ID=您的fkid
设置@RowCount=@@RowCount
如果(@RowCount<10000)中断
结束
最重要的是测试它是否是您的瓶颈问题,并避免过早优化


希望有帮助

您不能删除父表,因为它已连接到其他表。你会得到一个错误。您必须先删除所有相关的子项。您是否测试过它?您可以编写一个集成测试。检查发生了什么,停止时间,然后回滚。我了解级联和删除的工作原理。我想知道的是一个事务(删除父对象)与多个事务(一次删除部分子对象)的比较。这是我所期望的最接近的答案。
@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }
DECLARE @RowCount int
WHILE 1=1
    BEGIN
        DELETE TOP (10000) t1
        FROM table t1
        WHERE t1.FK_ID = yourFkId

        SET @RowCount = @@ROWCOUNT

        IF (@RowCount < 10000) BREAK
    END