ChatGPT解决这个技术问题 Extra ChatGPT

JPA 中的 CascadeType.REMOVE 和 orphanRemoval 有什么区别?

有什么区别

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

这个例子来自Java EE Tutorial,但我仍然不明白细节。

孤立删除意味着当与其“父”实体的关系被破坏时,依赖实体被删除。
写了一个test case来说明这个概念。

R
Rahul Tripathi

here:-

级联删除 用 CascadeType.REMOVE(或 CascadeType.ALL,包括 REMOVE)标记引用字段表示删除操作应自动级联到该字段引用的实体对象(集合字段可以引用多个实体对象): @Entity class Employee { : @OneToOne(cascade=CascadeType.REMOVE) 私有地址地址; : } Orphan Removal JPA 2 支持额外且更积极的移除级联模式,可以使用 @OneToOne 和 @OneToMany 注释的 orphanRemoval 元素指定:@Entity class Employee { : @OneToOne(orphanRemoval=true) private Address address; : } 区别:- 两种设置的区别在于对断开关系的响应。例如,当将地址字段设置为空或另一个地址对象时。如果指定了 orphanRemoval=true,则断开连接的 Address 实例将被自动删除。这对于清理在没有来自所有者对象(例如 Employee)的情况下不应该存在的依赖对象(例如地址)很有用。如果仅指定了 cascade=CascadeType.REMOVE,则不会采取自动操作,因为断开关系不是删除操作。


s
study

了解 CascadeType.REMOVEorphanRemoval=true 之间区别的简单方法。

对于孤立删除:如果您调用 setOrders(null),相关的 Order 实体将在 db 中自动删除。

对于删除级联:如果您调用 setOrders(null),则相关的 Order 实体将在 db 中自动删除。


删除 === 删除
M
Mr.Q

假设我们有一个子实体和一个父实体。一个父母可以有几个孩子。

@Entity
class parent {
  //id and other fields
 @OneToMany (orphanRemoval = "true",cascade = CascadeType.REMOVE)
   Set<Person> myChildern;
}

orphanRemoval 是一个 ORM 概念,它告诉孩子是否是孤儿。它也应该从数据库中删除。

当无法从其父级访问子级时,该子级将成为孤儿。例如,如果我们删除 Person 对象集(将其设置为空集)或将其替换为新集,则父级无法再访问旧集中的子级,并且子级将成为孤儿,因此子级注定要成为也在数据库中删除。

CascadeType.REMOVE 是一个数据库级别的概念,它告诉如果父表被删除,它在子表中的所有相关记录都应该被删除。


这个答案似乎更合乎逻辑,然后是这个线程上的任何其他答案。
V
Vlad Mihalcea

CascadeType.REMOVE

CascadeType.REMOVE 策略,您可以显式配置:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.REMOVE
)
private List<PostComment> comments = new ArrayList<>();

或从 CascadeType.ALL 策略隐式继承:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL
)
private List<PostComment> comments = new ArrayList<>();

允许您将 remove 操作从父实体传播到其子实体。

因此,如果我们获取父 Post 实体及其 comments 集合,并删除 post 实体:

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments
    where p.id = :id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

entityManager.remove(post);

Hibernate 将执行三个删除语句:

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

PostComment 子实体因 CascadeType.REMOVE 策略而被删除,就好像我们也删除了子实体一样。

孤儿移除策略

孤儿移除策略,需要通过 orphanRemoval 属性设置:

@OneToMany(
    mappedBy = "post",
    cascade = CascadeType.ALL,
    orphanRemoval = true
)
private List<PostComment> comments = new ArrayList<>();

允许您在从集合中删除子实体时删除子表行。

因此,如果我们加载 Post 实体及其 comments 集合并从 comments 集合中删除第一个 PostComment

Post post = entityManager.createQuery("""
    select p
    from Post p
    join fetch p.comments c
    where p.id = :id
    order by p.id, c.id
    """, Post.class)
.setParameter("id", postId)
.getSingleResult();

post.remove(post.getComments().get(0));

Hibernate 将为关联的 post_comment 表行执行 DELETE 语句:

DELETE FROM post_comment 
WHERE id = 2

g
garg10may

实际上,区别在于您是尝试更新数据(PATCH)还是完全替换数据(PUT)

假设您删除了 customer,而不是使用 cascade=REMOVE 也会删除看似有意和有用的客户订单。

@OneToMany(cascade=REMOVE, mappedBy="customer")
public List<Order> getOrders() { ... }

现在假设您使用 orphanRemoval="true" 更新了 customer,它将删除所有以前的订单并用提供的订单替换它们。 (PUT 根据 REST API

@OneToMany(mappedBy="customer", orphanRemoval="true")
public List<Order> getOrders() { ... }

如果没有 orphanRemoval,旧订单将被保留。 (PATCHREST API 方面)