JPA 2.0 orphanRemoval = true删除Cascade上的VS
我对JPA 2.0 orphanRemoval
属性有点困惑。
我想我可以看到它是需要的,当我使用我的JPA提供商的数据库生成工具创build基础数据库DDL ON DELETE CASCADE
上的特定关系。
但是,如果数据库存在并且关系上已经具有ON DELETE CASCADE
,那么这是否不足以级联删除? orphanRemoval
还做了什么?
干杯
orphanRemoval
与ON DELETE CASCADE
无关。
orphanRemoval
是一个完全ORM特定的事情 。 当它不再从“父”实体引用时,它标记“子”实体将被删除,例如,当您从相应的父实体集合中删除子实体时。
ON DELETE CASCADE
是一个特定于数据库的事物 ,当删除“父”行时,它会删除数据库中的“子”行。
从这里采取一个例子:
当一个Employee
实体对象被删除时,remove操作被级联到引用的Address
实体对象。 在这方面, orphanRemoval=true
和cascade=CascadeType.REMOVE
是相同的,如果指定orphanRemoval=true
, CascadeType.REMOVE
是多余的。
两个设置之间的区别在于断开关系的响应。 例如,如将地址字段设置为null
或另一个Address
对象时。
-
如果指定
orphanRemoval=true
则断开的Address
实例将被自动删除。 这对清理依赖对象(例如Address
)来说是非常有用的,该对象不应该在没有所有者对象(例如Employee
)的引用的情况下存在。 -
如果只指定
cascade=CascadeType.REMOVE
,则不会执行自动操作,因为断开关系不是删除操作。
为了避免由于孤儿删除而引起的悬挂引用,只能为包含私有非共享依赖对象的字段启用此function。
我希望这更清楚。
从集合中删除子实体的同时,您也将从DB中删除该子实体。 orphanRemoval也意味着你不能改变父母; 如果有一个部门有雇员,一旦你把这个雇员移到另一个部门,你就会不经意地把这个雇员从冲洗/提交(哪个先到者)中删除。 士气是把orphanRemoval设置为true,只要你确定那个父母的孩子不会在他们的存在中迁移到不同的父母。 打开orphanRemoval也会自动将REMOVE添加到级联列表中。
DDL ON DELETE CASCADE
的等效JPA映射是cascade=CascadeType.REMOVE
。 孤儿移除意味着当与其“父”实体的关系被破坏时,依赖实体被移除。 例如,如果一个孩子从@OneToMany
关系中删除,而没有在实体pipe理器中明确地删除它。
孤儿删除与ON DELETE CASCADE具有相同的效果,如下所示: – 假设我们在学生实体和引导实体之间有一个简单的多对一关系,许多学生可以映射到同一个引导,并且在数据库中有一个Student和Guide表之间的外键关系,以使学生表具有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名称部门Id_Guide
1罗伊欧洲经委会1
2 Nick ECE 1
指南表: –
ID名称薪水
1约翰$ 1500
现在,如果我想删除其中一个学生,使用
Student student1 = em.find(Student.class,1); em.remove(student1);
当一个学生logging被删除时,相应的指导logging也应该被删除,这就是Student实体中的CASCADE.REMOVE属性进入图片的位置,它的作用是:删除标识符为1的学生以及相应的引导对象(标识符1)。 但在这个例子中,还有一个学生对象被映射到相同的引导logging,除非我们在引导实体中使用orphanRemoval = true属性,否则上面的删除代码将不起作用。
@GaryK的答案是绝对伟大的,我花了一个小时寻找解释orphanRemoval = true
与CascadeType.REMOVE
,它帮助我理解。
总结: orphanRemoval = true
作用与CascadeType.REMOVE
相同如果我们删除对象( entityManager.delete(object)
),我们也希望子对象也被删除。
在完全不同的情况下,当我们获取像List<Child> childs = object.getChilds()
这样的一些数据,然后使用orphanRemoval=true
删除一个entityManager.remove(childs.get(0)
)将导致该实体对应于子对象childs.get(0)
将被从数据库中删除。