web-dev-qa-db-fra.com

Hibernate @OneToMany supprime l'enfant de la liste lors de la mise à jour du parent

J'ai les entités suivantes:

ÉQUIPE

@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;
}

}

et

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;
 }
}

Maintenant, lors de la mise à jour d'une entité Team qui contient par exemple Team.userTeamRoles = {UTR1, UTR2} avec {UTR1, UTR3}, je souhaite que UTR2 soit supprimé. Mais comme je le fais maintenant, l'ancienne liste reste la même et n'ajoute que UTR3 à la liste.

Voici comment je le fais en ce 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);

Je pensais qu'en faisant team.setUserTeamRoles(new HashSet<UserTeamRole>()); la liste serait réinitialisée et à cause des cascades la liste précédente serait supprimée.

Toute aide est appréciée. Merci

31
AndaP
  1. Au lieu de remplacer la collection (team.setUserTeamRoles(new HashSet<UserTeamRole>());), vous devez clear() celle existante. Cela se produit car si Hibernate charge l'entité (et ses collections) à partir de DB, il les "gère", c'est-à-dire. suit leurs changements. Généralement, lorsque vous utilisez Hibernate, il vaut mieux pas pour créer des setters pour les collections (listes, ensembles). Créez uniquement le getter et effacez la collection retournée par celui-ci, c'est-à-dire:

    team.getUserTeamRoles().clear();

  2. Une autre chose est que vous manquez la suppression orpheline (c.-à-d. Supprimer l'objet enfant lorsqu'il est supprimé de la collection dans le parent). Pour l'activer, vous devez ajouter @OneToMany(orphanRemoval=true) dans l'entité propriétaire.

92
Adam Dyga