简体   繁体   English

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

[英]What is the difference between CascadeType.REMOVE and orphanRemoval in JPA?

What's the difference between有什么区别

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

and

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

This example is from Java EE Tutorial, but I still don't understand details.这个例子来自Java EE Tutorial,但我还是不明白细节。

From here :-这里:-

Cascading Remove级联删除

Marking a reference field with CascadeType.REMOVE (or CascadeType.ALL, which includes REMOVE) indicates that remove operations should be cascaded automatically to entity objects that are referenced by that field (multiple entity objects can be referenced by a collection field):使用 CascadeType.REMOVE(或 CascadeType.ALL,包括 REMOVE)标记引用字段表示移除操作应该自动级联到该字段引用的实体对象(多个实体对象可以被一个集合字段引用):

 @Entity class Employee { : @OneToOne(cascade=CascadeType.REMOVE) private Address address; : }

Orphan Removal孤儿移除

JPA 2 supports an additional and more aggressive remove cascading mode which can be specified using the orphanRemoval element of the @OneToOne and @OneToMany annotations: JPA 2 支持额外的和更积极的删除级联模式,可以使用 @OneToOne 和 @OneToMany 注释的 orphanRemoval 元素指定:

 @Entity class Employee { : @OneToOne(orphanRemoval=true) private Address address; : }

DIFFERENCE:-区别:-

The difference between the two settings is in the response to disconnecting a relationship.两种设置之间的区别在于对断开关系的响应。 For example, such as when setting the address field to null or to another Address object.例如,当将地址字段设置为 null 或另一个地址对象时。

  • If orphanRemoval=true is specified the disconnected Address instance is automatically removed.如果指定了orphanRemoval=true,则自动删除断开连接的 Address 实例。 This is useful for cleaning up dependent objects (eg Address) that should not exist without a reference from an owner object (eg Employee).这对于清理在没有所有者对象(例如员工)的引用的情况下不应该存在的依赖对象(例如地址)很有用。
  • If only cascade=CascadeType.REMOVE is specified no automatic action is taken since disconnecting a relationship is not a remove如果仅指定了cascade=CascadeType.REMOVE则不会采取自动操作,因为断开关系不是删除
    operation.手术。

An easy way to understand the difference between CascadeType.REMOVE and orphanRemoval=true .了解CascadeType.REMOVEorphanRemoval=true之间区别的简单方法。

For orphan removal: If you invoke setOrders(null) , the related Order entities will be removed in db automatically.对于孤儿移除:如果您调用setOrders(null) ,相关的Order实体将在 db 中自动移除。

For remove cascade: If you invoke setOrders(null) , the related Order entities will NOT be removed in db automatically.对于删除级联:如果您调用setOrders(null) ,相关的Order实体将不会在 db 中自动删除。

Suppose we have a child entity and a parent entity.假设我们有一个子实体和一个父实体。 A parent can have several children.一个父母可以有几个孩子。

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

The orphanRemoval is an ORM concept, it tells if the child is orphaned. orphanRemoval 是一个 ORM 概念,它告诉孩子是否是孤儿。 it should also be removed from the database.它也应该从数据库中删除。

A child is orphaned when it can`t be accessed from its parent.当孩子无法从其父级访问时,它就是孤儿。 For example, if we remove the Person objects set (setting it to an empty set) or replace it with a new set then the parent can no longer access the children in the old set and the children are orphaned so the children are doomed to be removed in the database also.例如,如果我们删除 Person 对象集(将其设置为空集)或将其替换为新集,那么父对象将无法再访问旧集合中的子对象,并且子对象是孤立的,因此子对象注定数据库中也删除了。

CascadeType.REMOVE is a database level concept and it tells if the parent is removed, all its related records in the child table should be removed. CascadeType.REMOVE 是一个数据库级别的概念,它告诉如果父表被删除,它在子表中的所有相关记录都应该被删除。

CascadeType.REMOVE级联类型.REMOVE

The CascadeType.REMOVE strategy, which you can configure explicitly: CascadeType.REMOVE策略,您可以明确配置:

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

or inherit it implicitly from the CascadeType.ALL strategy:或者从CascadeType.ALL策略隐式继承它:

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

allows you to propagate the remove operation from the parent entity to its child entities.允许您将remove操作从父实体传播到其子实体。

So, if we fetch the parent Post entity along with its comments collection, and remove the post entity:因此,如果我们获取父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 is going to execute three delete statements: Hibernate 将执行三个删除语句:

DELETE FROM post_comment 
WHERE id = 2

DELETE FROM post_comment 
WHERE id = 3

DELETE FROM post 
WHERE id = 1

The PostComment child entities were deleted because of the CascadeType.REMOVE strategy, which acted as if we removed the child entities as well.由于CascadeType.REMOVE策略, PostComment子实体被删除,就像我们也删除了子实体一样。

The orphan-removal strategy孤儿清除策略

The orphan-removal strategy, which needs to be set via the orphanRemoval attribute:孤儿移除策略,需要通过orphanRemoval属性设置:

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

allows you to remove the child table row upon removing the child entity from the collection.允许您在从集合中删除子实体时删除子表行。

So, if we load the Post entity along with its comments collection and remove the first PostComment from the comments collection:因此,如果我们加载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 is going to execute a DELETE statement for the associated post_comment table row: Hibernate 将为关联的post_comment表行执行 DELETE 语句:

DELETE FROM post_comment 
WHERE id = 2

Practically the difference lies in whether you are trying to update the data (PATCH) or entirely replace the data (PUT)实际上区别在于您是尝试更新数据(PATCH)还是完全替换数据(PUT)

Let's say you delete the customer than using cascade=REMOVE will also remove that customers orders which seem intended and useful.假设您删除customer不是使用cascade=REMOVE还将删除那些看起来有意且有用的客户订单。

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

Now let's say you update a customer with orphanRemoval="true" it will delete all previous orders and replace them with the one provided.现在假设您使用orphanRemoval="true"更新customer ,它将删除所有以前的订单并将其替换为提供的订单。 ( PUT in terms of REST API ) PUT来讲REST API

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

Without orphanRemoval old orders would be kept.如果没有orphanRemoval旧订单将被保留。 ( PATCH in terms of REST API ) REST API方面的PATCH

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 @CascadeOnDelete和CascadeType.REMOVE批注有什么区别? - What's the difference between @CascadeOnDelete and CascadeType.REMOVE annotations? JPA:&#39;CascadeType.REMOVE&#39;或&#39;orphanRemoval = true&#39;,它们在:n关系中使用,用EmbeddeId类生成新的表/类? - JPA: 'CascadeType.REMOVE' or 'orphanRemoval = true', which use in a n:n relation that generate new table/class with EmbeddeId class? JPA CascadeType.REMOVE不会删除reshipsship的子级 - JPA CascadeType.REMOVE not deleting children of a relashionship 没有 CascadeType.REMOVE 的 CascadeType.ALL 更改持久化行为 - CascadeType.ALL without CascadeType.REMOVE changes persist behavior @ManyToMany with cascade = CascadeType.REMOVE删除关联和实体 - @ManyToMany with cascade = CascadeType.REMOVE removes associations AND entities Hibernate:无法删除对象 - 外键约束 - CascadeType.REMOVE - Hibernate: Cannot Delete Object - foreign key constraint - CascadeType.REMOVE 具有仅CascadeType.REMOVE的双向@OneToOne保存更改:不需要 - Bi-directional @OneToOne with ONLY CascadeType.REMOVE saves changes: that is not wanted Hibernate在ManyToMany关系中生成其他查询,而没有设置CascadeType.REMOVE - Hibernate generate additional query in ManyToMany relation while no CascadeType.REMOVE is set @cascade(cascadeType.Delete)和cascade = cascadeType.Delete之间的区别 - Difference between @cascade(cascadeType.Delete) and cascade=cascadeType.Delete Hibernate JPA在find()和merge()之间的区别 - Hibernate JPA difference in remove between find() and merge()
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM