休眠:什么时候应该使用Cascade.ALL,什么时候应该分别指定它们

时间:2019-09-23 02:16:16

标签: java hibernate spring-boot

我通常用one-to-many注释我的many-to-manymany-to-oneCascadeType.ALL关系,因为它们为我提供了我需要的所有功能。但是我觉得这将来可能会导致我遇到一些问题。使用CascadeType.ALL可以吗?我应该注意什么,为什么不使用它?

4 个答案:

答案 0 :(得分:2)

级联是关于涉及一个对象通过关联传播到其他对象的持久性动作。

级联可以应用于各种Hibernate动作,通常是可传递的。定义关联的注释的“ cascade = CascadeType ...” 属性指出应为该关联级联哪些操作。

Cascade =“ all” 表示应用所有主要的层叠类型。

从Hibernate 5.3开始,这些类型是:

  • “删除” /“删除”,
  • “分离” /“逐出”,
  • “合并”,
  • “锁定”,
  • “坚持”,
  • “刷新”,
  • “复制”,
  • “保存更新” /“更新”

(某些级联类型名称过旧和/或已弃用。)

还有三种复合类型:

  • “ all_delete_orphan” -表示与“ all”相同,并允许删除级联孤立的实体。
  • “删除孤儿” -表示“删除”加孤儿删除。
  • “无” -表示无级联。

答案 1 :(得分:1)

CascadeType.ALL是什么意思,什么时候应该使用?

CascadeType.ALL是在持久化上下文中传播到关联实体到相关实体的所有操作(PERSIST, MERGE, REMOVE, REFRESH, DETACH)

因此,这个问题非常笼统,如果您知道这些定义,就可以确定是否有必要使用CascadeType.ALL

文档:

EntityManager的API可以保留新实体,remove(删除)现有实体,refresh实体状态从数据存储区,以及merge分离的实体状态返回到持久性上下文。

EntityManager执行上述操作时,您可以指示它使用元数据批注的层叠属性将操作自动层叠到持久字段中保存的实体。此过程是递归的。级联属性接受一个CascadeType枚举值数组。

CascadeType.PERSIST :持久化实体时,还持久化此字段中保存的实体。我们建议自由应用此级联规则,因为如果EntityManager在刷新期间找到引用新实体的字段,并且该字段未使用CascadeType.PERSIST,则是错误的。

CascadeType.MERGE :合并实体状态时,还要合并此字段中保存的实体。

CascadeType.REMOVE :删除实体时,还要删除此字段中保存的实体。

CascadeType.REFRESH :刷新实体时,还刷新该字段中保存的实体。

CascadeType.DETACH :分离实体时,还分离该字段中保存的实体。

参考:

EJB3.0 Specification - 2.1.7 Entity Relationships

Apache-openjpa docs JPA overview meta cascade

答案 2 :(得分:0)

这是您需要了解的东西。首先,您设计数据库的效率还取决于表是否独立或与另一个表有任何关系。请看以下几点:

  1. 如果您的表与另一个表具有多个链接,并且持久存储在单个表中的数据应将数据级联到所有从属表,则在这种情况下,您必须使用CascadeType.ALL例如:

EmployeeEntity.java

@Entity
@Table(name = "Employee")
public class EmployeeEntity implements Serializable
{
    private static final long serialVersionUID = -1798070786993154676L;
    @Id
    @Column(name = "ID", unique = true, nullable = false)
    private Integer           employeeId;
    @Column(name = "FIRST_NAME", unique = false, nullable = false, length = 100)
    private String            firstName;
    @Column(name = "LAST_NAME", unique = false, nullable = false, length = 100)
    private String            lastName;

    @OneToMany(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name="EMPLOYEE_ID")
    private Set<AccountEntity> accounts;

    //Getters and Setters Ommited
}

AccountEntity.java

@Entity
@Table(name = "Account")
public class AccountEntity implements Serializable
{
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "ID", unique = true, nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Integer           accountId;
    @Column(name = "ACC_NO", unique = false, nullable = false, length = 100)
    private String            accountNumber;

    @OneToOne (mappedBy="accounts",  fetch = FetchType.LAZY)
    private EmployeeEntity employee;

}

查看上面的EmployeeEntity.java源代码。它定义了“ cascade = CascadeType.ALL”,从本质上讲意味着在EmployeeEntity上发生的任何更改也必须级联到AccountEntity。如果您保存员工,则所有关联的帐户也将保存到数据库中。如果删除雇员,则与该雇员关联的所有帐户也将被删除。很简单。

但是,如果我们只希望级联仅保存操作而不是删除操作,该怎么办?然后我们需要使用以下代码明确指定它。

@OneToMany(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name="EMPLOYEE_ID")
private Set<AccountEntity> accounts;

JPA中没有默认的层叠类型。默认情况下,没有操作级联。

答案 3 :(得分:0)

除上述观点外,还要补充以下几点。 从面向对象的角度来看,我们应该从组合与聚合的角度来考虑。 在Java中,与使用FK键的DB中不同,我们无法强制父母与孩子之间建立严格的关系。

从概念上讲,休眠状态的CASCADE选项使我们能够维持这种严格的关系。