在 Hibernate 中删除大型实体的最佳策略
Best strategy to delete a large entity in Hibernate
我有一个 parent 实体,它在 Web 应用程序中有许多子集合。删除该实体的最佳策略是什么?我可以只删除 parent 并且所有 children 集合将因级联而被删除。但我担心这会花费很长时间,并且可能会导致 table 锁定,从而影响其他用户。或者我可以删除每个 children 并删除最后的 parent 实体。什么是最好的方法?
一次删除 parent 和 children。我用这个。
entityManger.remove(parent); -> one transaction
或者我可以遍历每个 children 集合并首先删除所有 children,最后删除 parent。这会将一笔大交易拆分成许多小交易。
只有parent没有children才可以。在处理 parent.
之前,您必须先删除所有 children
@OneToMany 默认策略 fetch = FetchType.LAZY
级联类型 ALL、PERSIST、MERGE、REMOVE、REFRESH、DETACH。
如果您想删除带有子集合的父集合。您更改父级联 = {cascadeType.REMOVE 和 ALL}
您没有定义 cascadeType.REMOVE。采取错误(违反 db-fk-key-constraint)
@Entity
public class Company {
@OneToMany(mappedBy = "company", cascade = { CascadeType.REMOVE })
private List<ExhibitionGroup> exhibitionGroup;
...
}
@Entity
public class ExhibitionGroup {
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
...
}
或使用
@OneToMany(mappedBy = "company", orphanRemoval = ture)
Orphan Removal in Relationships
When a target entity in one-to-one or one-to-many relationship is removed from the relationship, it is often desirable to cascade the remove operation to the target entity. Such target entities are considered “orphans,” and the orphanRemoval attribute can be used to specify that orphaned entities should be removed. For example, if an order has many line items and one of them is removed from the order, the removed line item is considered an orphan. If orphanRemoval is set to true, the line item entity will be deleted when the line item is removed from the order.
@OneToMany 和@oneToOne 中的 orphanRemoval 属性采用布尔值,默认为 false。
当从关系中删除孤立的客户实体时,以下示例会将删除操作级联到孤立的客户实体:
@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }
所有其他答案似乎都没有解决您的问题。
首先,除非您正在处理大量使用 table 或按顺序或数百万删除,否则您不会面临任何重大的性能问题。
但是,如果您确实遇到上述情况,您可以做几件事(并且您必须在性能或 ROW 锁定预防之间做出选择)
1) 确保你的外键中有索引
2) 按照你说的进行批量删除。这将防止锁定,但会降低性能,因为应用程序需要调用多个语句到数据库。更多信息在这里 https://vladmihalcea.com/how-to-batch-delete-statements-with-hibernate/
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
最重要的是测试是否是你的瓶颈问题,避免过早优化。
希望对你有帮助
我有一个 parent 实体,它在 Web 应用程序中有许多子集合。删除该实体的最佳策略是什么?我可以只删除 parent 并且所有 children 集合将因级联而被删除。但我担心这会花费很长时间,并且可能会导致 table 锁定,从而影响其他用户。或者我可以删除每个 children 并删除最后的 parent 实体。什么是最好的方法? 一次删除 parent 和 children。我用这个。
entityManger.remove(parent); -> one transaction
或者我可以遍历每个 children 集合并首先删除所有 children,最后删除 parent。这会将一笔大交易拆分成许多小交易。
只有parent没有children才可以。在处理 parent.
之前,您必须先删除所有 children@OneToMany 默认策略 fetch = FetchType.LAZY
级联类型 ALL、PERSIST、MERGE、REMOVE、REFRESH、DETACH。
如果您想删除带有子集合的父集合。您更改父级联 = {cascadeType.REMOVE 和 ALL}
您没有定义 cascadeType.REMOVE。采取错误(违反 db-fk-key-constraint)
@Entity
public class Company {
@OneToMany(mappedBy = "company", cascade = { CascadeType.REMOVE })
private List<ExhibitionGroup> exhibitionGroup;
...
}
@Entity
public class ExhibitionGroup {
@ManyToOne
@JoinColumn(name = "company_id")
private Company company;
...
}
或使用
@OneToMany(mappedBy = "company", orphanRemoval = ture)
Orphan Removal in Relationships When a target entity in one-to-one or one-to-many relationship is removed from the relationship, it is often desirable to cascade the remove operation to the target entity. Such target entities are considered “orphans,” and the orphanRemoval attribute can be used to specify that orphaned entities should be removed. For example, if an order has many line items and one of them is removed from the order, the removed line item is considered an orphan. If orphanRemoval is set to true, the line item entity will be deleted when the line item is removed from the order.
@OneToMany 和@oneToOne 中的 orphanRemoval 属性采用布尔值,默认为 false。
当从关系中删除孤立的客户实体时,以下示例会将删除操作级联到孤立的客户实体:
@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }
所有其他答案似乎都没有解决您的问题。
首先,除非您正在处理大量使用 table 或按顺序或数百万删除,否则您不会面临任何重大的性能问题。
但是,如果您确实遇到上述情况,您可以做几件事(并且您必须在性能或 ROW 锁定预防之间做出选择)
1) 确保你的外键中有索引
2) 按照你说的进行批量删除。这将防止锁定,但会降低性能,因为应用程序需要调用多个语句到数据库。更多信息在这里 https://vladmihalcea.com/how-to-batch-delete-statements-with-hibernate/
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
最重要的是测试是否是你的瓶颈问题,避免过早优化。
希望对你有帮助