On delete set null in hibernate in @OneToMany
Asked Answered
Q

3

28

I have a Department entity which relations are as follows:

  1. Many departments can be in one parent department:

    @ManyToOne
    @JoinColumn(name = "ik_parent_department_id")
    private Department parentDepartment;
    
  2. One parent department can have many departments:

    @OneToMany(mappedBy = "parentDepartment")
    private Set<Department> children = new HashSet<Department>(0);
    

And I want to implement the next: When I delete a department, then the ik_parent_department_id parameter of all children of this department is set to null. Any ideas how to do that?

Quotable answered 23/11, 2011 at 13:56 Comment(1)
possible duplicate of Have JPA/Hibernate to replicate the "ON DELETE SET NULL" functionalityColonnade
D
13

You'll have to set the children's ik_parent_department_id to null explicitly.

Department parentDepartment = (Department) session.load(Department.class, id);
session.delete(parentDepartment);
for (Department child : parentDepartment.getChildren()){
    child.setParentDepartment(null);
} 
session.flush();

With cascading you would only manage to delete child Departments.

Dishevel answered 23/11, 2011 at 14:7 Comment(1)
No there is not. It is possible to set up the fk in the db to do this in some databases but the support is limited. E.g. with sql server you run into problems with circle references so implementing the logic into the code looks like proposed. See also: #9944637Colonnade
O
14

With JPA, in parent Entity you might have something like

@OneToMany(mappedBy="parent", cascade={CascadeType.PERSIST})
Collection<Child> children;

and in order to avoid possible repeating "set null code" & integrity violation exceptions on parent removal implement in parent Entity also

@PreRemove
private void preRemove() {
   children.forEach( child -> child.setParent(null));
}
Organon answered 22/11, 2017 at 12:53 Comment(1)
Thanks. This works. My question is: Is there a way of doing this only with cascade operations?Westernmost
D
13

You'll have to set the children's ik_parent_department_id to null explicitly.

Department parentDepartment = (Department) session.load(Department.class, id);
session.delete(parentDepartment);
for (Department child : parentDepartment.getChildren()){
    child.setParentDepartment(null);
} 
session.flush();

With cascading you would only manage to delete child Departments.

Dishevel answered 23/11, 2011 at 14:7 Comment(1)
No there is not. It is possible to set up the fk in the db to do this in some databases but the support is limited. E.g. with sql server you run into problems with circle references so implementing the logic into the code looks like proposed. See also: #9944637Colonnade
B
6

Just code it:

for (Department child : parent.getChildren()) {
    child.setParentDepartment(null);
}
session.delete(parent);
Brigade answered 23/11, 2011 at 14:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.