[英]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,但我还是不明白细节。
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.REMOVE
和orphanRemoval=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 是一个数据库级别的概念,它告诉如果父表被删除,它在子表中的所有相关记录都应该被删除。
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, 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.