Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate @OneToMany remove child from list when updating parent

I have the following entities:

TEAM

@Entity @Table public class Team { [..] private Set<UserTeamRole> userTeamRoles;  /**  * @return the userTeamRoles  */ @OneToMany(cascade = { CascadeType.ALL }, mappedBy = "team", fetch = FetchType.LAZY) public Set<UserTeamRole> getUserTeamRoles() {     return userTeamRoles; }  /**  * @param userTeamRoles  *            the userTeamRoles to set  */ public void setUserTeamRoles(Set<UserTeamRole> userTeamRoles) {     this.userTeamRoles = userTeamRoles; } 

}

and

USER_TEAM_ROLE

@Entity @Table(name = "user_team_role") public class UserTeamRole {   @ManyToOne(cascade = CascadeType.MERGE, fetch = FetchType.LAZY)  @JoinColumn(name = "FK_TeamId")  public Team getTeam() {     return team;  } } 

Now, when updating a Team entity that contains for example Team.userTeamRoles = {UTR1, UTR2} with {UTR1, UTR3}, I want UTR2 to be deleted. But the way I do it now, the old list remains the same and it only adds UTR3 to the list.

This is how I do it at the moment:

 if (!usersDualListData.getTarget().isEmpty()) {         // the role for each user within the team will be "employee"         team.setUserTeamRoles(new HashSet<UserTeamRole>());         Role roleForUser = roleService                 .getRoleByName(RoleNames.ROLE_EMPLOYEE.name());         for (User user : usersDualListData.getTarget()) {             UserTeamRole utr = new UserTeamRole();             utr.setUser(user);             utr.setTeam(team);             utr.setRole(roleForUser);             team.getUserTeamRoles().add(utr);         }     }  teamService.updateTeam(team); 

I thought that by doing team.setUserTeamRoles(new HashSet<UserTeamRole>()); the list would be reset and because of the cascades the previous list would be deleted.

Any help is appreciated. Thank you

like image 837
AndaP Avatar asked Feb 04 '13 12:02

AndaP


People also ask

How do you delete child records when parent is deleted in hibernate?

The correct way is to create the foreign key on mail to reference account . With ON DELETE CASCADE , you tell MySQL that it should delete a row (whose table has the foreign key) if its parent (referenced by the key) is deleted.

How do I delete a child entity from one to many relationship?

Then how do we delete the child entity from the database? Hibernate does that automatically when you set the orphanRemoval attribute of the @OneToMany annotation to true and the cascade attribute to CascadeType. ALL , it auto delete child entities while deleting parent. CascadeType.

What is orphan removal in Hibernate?

REMOVE . Orphan removal means that dependent entities are removed when the relationship to their "parent" entity is destroyed. For example if a child is removed from a @OneToMany relationship without explicitely removing it in the entity manager.


1 Answers

  1. Instead of replacing the collection (team.setUserTeamRoles(new HashSet<UserTeamRole>());) you have to clear() the existing one. This happens because if Hibernate loads the entity (and its collections) from DB, it "manages" them, ie. tracks their changes. Generally when using Hibernate it's better not to create any setters for collections (lists, sets). Create only the getter, and clear the collection returned by it, ie:

    team.getUserTeamRoles().clear();

  2. Another thing is that you miss orphan deletion (ie. delete child object when it's removed from collection in the parent). To enable it, you need to add @OneToMany(orphanRemoval=true) in owning entity.

like image 100
Adam Dyga Avatar answered Sep 17 '22 09:09

Adam Dyga