Hibernate JPA-orphaneremovation=true与ON-DELETE-CASCADE-DML子句有何不同
我对JPA2.0的属性有点困惑 我想当我使用我的JPA提供者的DB生成工具来创建底层数据库DDL,以便在特定关系上有一个关于删除级联的Hibernate JPA-orphaneremovation=true与ON-DELETE-CASCADE-DML子句有何不同,hibernate,jpa,cascade,cascading-deletes,orphan-removal,Hibernate,Jpa,Cascade,Cascading Deletes,Orphan Removal,我对JPA2.0的属性有点困惑 我想当我使用我的JPA提供者的DB生成工具来创建底层数据库DDL,以便在特定关系上有一个关于删除级联的时,我可以看出这是必要的 但是,如果数据库存在,并且它在关系上已经有了一个关于删除级联的,这还不足以适当地级联删除吗?除此之外,删除还有什么作用 Cheers删除级联上DDL的等效JPA映射为CASCADE=CascadeType。删除。孤立删除意味着当与其“父”实体的关系被破坏时,从属实体将被删除。例如,如果从@OneToMany关系中删除了一个子项,而没有在实
时,我可以看出这是必要的
但是,如果数据库存在,并且它在关系上已经有了一个关于删除级联的
,这还不足以适当地级联删除吗?除此之外,删除
还有什么作用
Cheers删除级联上DDL
的等效JPA映射为CASCADE=CascadeType。删除
。孤立删除意味着当与其“父”实体的关系被破坏时,从属实体将被删除。例如,如果从@OneToMany
关系中删除了一个子项,而没有在实体管理器中明确删除该子项。孤立删除
与删除级联上的无关
孤儿删除
是一件完全ORM特有的事情。当不再从“父”实体引用“子”实体时(例如,从父实体的相应集合中删除子实体时),它将标记要删除的“子”实体
ON DELETE CASCADE
是一个特定于数据库的东西,它在删除“父”行时删除数据库中的“子”行。从集合中删除子实体的那一刻,也将从数据库中删除该子实体。移除孤儿也意味着你不能改变父母;如果有一个部门有员工,一旦你将该员工调到另一个部门,你就会在刷新/提交时(首先是哪个部门)无意中将该员工从DB中调离。只要你确信父母的孩子在他们的一生中不会迁移到另一个父母,你的士气就是将孤儿移除设置为真。启用“删除”也会自动将删除添加到级联列表中。示例如下:
删除员工
实体对象时,删除操作将级联到引用的地址
实体对象。在这方面,orphanRemoving=true
和cascade=CascadeType.REMOVE
是相同的,如果指定了orphanRemoving=true
,则CascadeType.REMOVE
是多余的
这两种设置之间的区别在于对断开关系的响应。例如,当将地址字段设置为null
或另一个address
对象时
- 如果指定了断开连接的
地址
实例
将自动删除。这对于清除依赖项非常有用
如果没有来自的引用,则不应存在的对象(例如地址
)
所有者对象(例如员工
)
- 如果仅指定了
cascade=CascadeType.REMOVE
,则不执行自动操作
由于断开关系不是移除,因此采取了
手术
为了避免由于孤立删除而挂起引用,应仅为包含私有非共享从属对象的字段启用此功能
我希望这能让事情变得更清楚。孤立删除与以下场景中的删除级联具有相同的效果:-
假设我们在学生实体和指南实体之间有一个简单的多对一关系,其中许多学生可以映射到同一个指南,并且在数据库中,我们在学生和指南表之间有一个外键关系,这样学生表的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);
这里我们用两个不同的student对象映射同一个指南,由于使用了CASCADE.PERSIST,对象图将如下所示保存在数据库表中(在我的例子中是MySql)
学生表:-
ID名称部门ID\U指南
1是的1
2矛盾1
指南表:-
ID姓名工资
约翰1500美元
现在如果我想删除其中一个学生,使用
Student student1 = em.find(Student.class,1);
em.remove(student1);
当一个学生记录被删除时,相应的指南记录也应该被删除,这就是学生实体中的CASCADE.REMOVE属性进入图片的地方,它的作用是什么;它删除标识符为1的学员以及相应的向导对象(标识符1)。但在本例中,还有一个学生对象映射到同一指南记录,除非我们在指南实体中使用orphanRemoving=true属性,否则上面的删除代码将无法工作。@GaryK answer绝对不错,我花了一个小时寻找解释,它帮助我理解了
总结:orphanRemoving=true
的工作原理与CascadeType相同。只有当我们删除对象(entityManager.delete(object)
)并且希望同时删除childs对象时,才能删除
在完全不同的位置,当我们获取一些数据时,如List childs=object.getChilds()
,然后使用orphandremove=true
删除子对象(entityManager.remove(childs.get(0)
),将导致该实体对应于childs.get(0)
将从数据库中删除。区别在于:
-OrphanRemoving=true:“子”实体在不再被引用时被删除(其父实体可能不会被删除)。
-CascadeType.REMOVE:“子”实体只有在其“父”实体被删除时才会被删除。实体状态转换
JPA将实体状态转换转换为SQL语句,如INSERT、UPDATE或DELETE
当您持久化
一个实体时,您正在计划在实体管理器运行时执行INSERT语句
Student student1 = em.find(Student.class,1);
em.remove(student1);
@OneToMany(
mappedBy = "post",
cascade = CascadeType.ALL,
orphanRemoval = true
)
private List<Comment> comments = new ArrayList<>();
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
entityManager.remove(post);
DELETE FROM post_comment WHERE id = 1
DELETE FROM post_comment WHERE id = 2
DELETE FROM post WHERE id = 1
Post post = entityManager.find(Post.class, 1L);
assertEquals(2, post.getComments().size());
PostComment postComment = post.getComments().get(0);
assertEquals(1L, postComment.getId());
post.getComments().remove(postComment);
DELETE FROM post_comment WHERE id = 1
ALTER TABLE post_comment
ADD CONSTRAINT fk_post_comment_post_id
FOREIGN KEY (post_id) REFERENCES post
ON DELETE CASCADE;
DELETE FROM post WHERE id = 1