JPA 2.0 orphanRemoval = true VS删除级联

我对JPA2.0
orphanRemoval
属性感到有点困惑。 当我使用我的JPA提供程序的数据库生成工具来创建底层数据库DDL以在特定关系上具有
ON DELETE CASCADE
时,我想我可以看到它是必需的。 但是,如果数据库存在且关系上已经有一个
ON DELETE CASCADE
,这是不是足以级联删除?
orphanRemoval
又做了什么? 干杯     
已邀请:
orphanRemoval
ON DELETE CASCADE
无关。
orphanRemoval
完全是ORM特有的。它标记“子”实体,当它不再从“父”实体引用时被删除,例如从父实体的相应集合中删除子实体时。
ON DELETE CASCADE
是特定于数据库的东西,当删除“父”行时,它会删除数据库中的“子”行。     
这里采用的示例如下: 删除
Employee
实体对象时,删除操作将级联到引用的
Address
实体对象。在这方面,
orphanRemoval=true
cascade=CascadeType.REMOVE
是相同的,如果指定
orphanRemoval=true
,则
CascadeType.REMOVE
是多余的。 两个设置之间的区别在于断开关系的响应。例如,将地址字段设置为
null
或另一个
Address
对象时。 如果指定
orphanRemoval=true
则断开
Address
实例 自动删除。这对清理依赖很有用 没有引用的对象(例如
Address
)不应该存在 所有者对象(例如
Employee
)。 如果仅指定
cascade=CascadeType.REMOVE
,则不执行自动操作 因为断开关系不是一个删除 操作。 为避免因孤立删除而悬挂引用,仅应为包含私有非共享依赖对象的字段启用此功能。 我希望这更清楚。     
从集合中删除子实体的那一刻,您也将从数据库中删除该子实体。 orphanRemoval也暗示你不能改变父母;如果有一个部门有员工,一旦你删除该员工将其放入另一个部门,你就会在刷新/提交时无意中从数据库中删除该员工(无论哪个先行)。士气是将orphanRemoval设置为true,只要您确定该父级的子女在其存在期间不会迁移到不同的父级。启用orphanRemoval还会自动将REMOVE添加到级联列表中。     
DDL
ON DELETE CASCADE
的等效JPA映射是
cascade=CascadeType.REMOVE
。孤立删除意味着在与其“父”实体的关系被销毁时删除依赖实体。例如,如果某个孩子从
@OneToMany
关系中删除而未在实体管理器中明确删除它。     
@GaryK答案非常棒,我花了一个小时寻找解释
orphanRemoval = true
vs
CascadeType.REMOVE
,这帮助我理解。 总结:
orphanRemoval = true
CascadeType.REMOVE
完全相同只要我们删除对象(
entityManager.delete(object)
)并且我们也希望删除子对象。 在完全不同的情况下,当我们获取一些数据如
List<Child> childs = object.getChilds()
然后使用
orphanRemoval=true
删除一个孩子(
entityManager.remove(childs.get(0)
)将导致对应于
childs.get(0)
的实体将从数据库中删除。     
在以下情形中,孤立删除与ON DELETE CASCADE具有相同的效果: - 假设我们在学生实体和指南实体之间有一个简单的多对一关系,其中许多学生可以映射到同一指南,在数据库中我们在学生和指南表之间有外键关系,这样学生表的id_guide为FK 。
    @Entity
    @Table(name = "student", catalog = "helloworld")
    public class Student implements java.io.Serializable {
     @Id
     @GeneratedValue(strategy = IDENTITY)
     @Column(name = "id")
     private Integer id;

    @ManyToOne(cascade={CascadeType.PERSIST,CascadeType.REMOVE})
    @JoinColumn(name = "id_guide")
    private Guide guide;
//父实体
    @Entity
    @Table(name = "guide", catalog = "helloworld")
    public class Guide implements java.io.Serializable {

/**
 * 
 */
private static final long serialVersionUID = 9017118664546491038L;

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Integer id;

@Column(name = "name", length = 45)
private String name;

@Column(name = "salary", length = 45)
private String salary;


 @OneToMany(mappedBy = "guide", orphanRemoval=true) 
 private Set<Student> students = new  HashSet<Student>(0);
在这种情况下,关系是学生实体是关系的所有者,因此我们需要保存学生实体以便保持整个对象图,例如
    Guide guide = new Guide("John", "$1500");
    Student s1 = new Student(guide, "Roy","ECE");
    Student s2 = new Student(guide, "Nick", "ECE");
    em.persist(s1);
    em.persist(s2);
这里我们使用两个不同的学生对象映射相同的指南,并且由于使用了CASCADE.PERSIST,因此对象图将在数据库表中保存如下(在我的情况下为MySql) 学生表: - ID Name Dept Id_Guide 1&nbsp;&nbsp;&nbsp;&nbsp; Roy&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ECE&nbsp;&nbsp;&nbsp;&nbsp; 1 2&NBSP;&NBSP;&NBSP;&NBSP;尼克&NBSP;&NBSP;&NBSP;&NBSP; ECE&NBSP;&NBSP;&NBSP;&NBSP; 1 指南表: - ID NAME薪水 1&NBSP;&NBSP;&NBSP;&NBSP;&约翰NBSP;&NBSP;&NBSP;&NBSP;&NBSP; $ 1500 现在,如果我想删除其中一个学生,请使用
      Student student1 = em.find(Student.class,1);
      em.remove(student1);
当删除学生记录时,也应删除相应的指南记录,即学生实体中的CASCADE.REMOVE属性进入图片及其作用的位置;它将删除具有标识符1的学生以及相应的指南对象(标识符) 1)。但是在这个例子中,还有一个学生对象被映射到同一个指南记录,除非我们在指南实体中使用orphanRemoval = true属性,否则上面的删除代码将不起作用。     
不同之处是: - orphanRemoval = true:“Child”实体在不再引用时被删除(其父级可能不会被删除)。 - CascadeType.REMOVE:仅当删除“父”时才删除“子”实体。     

要回复问题请先登录注册