2013-02-04 9 views
27

ho le seguenti entità:Hibernate @OneToMany rimuovere figlio dalla lista quando si aggiorna genitore

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

}

e

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

Ora , durante l'aggiornamento di un'entità Team che contiene ad esempio Team.userTeamRoles = {UTR1, UTR2} con {UTR1, UTR3}, voglio che UTR2 sia cancellato. Ma nel modo in cui lo faccio ora, la vecchia lista rimane la stessa e aggiunge solo UTR3 alla lista.

Questo è come lo faccio in questo momento:

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

ho pensato che facendo team.setUserTeamRoles(new HashSet<UserTeamRole>()); la lista sarebbe essere resettato e per le cascate della lista precedente sarebbe soppresso.

Qualsiasi aiuto è apprezzato. Grazie

+0

Penso che sia lo stesso problema qui: http://stackoverflow.com/questions/2011519/jpa-onetomany-not-deleting-child check it out! –

risposta

82
  1. Invece di sostituire la raccolta (team.setUserTeamRoles(new HashSet<UserTeamRole>());) bisogna clear() quello esistente. Questo accade perché se Hibernate carica l'entità (e le sue raccolte) dal DB, le "gestisce", cioè. tiene traccia delle loro modifiche. Generalmente quando si usa Hibernate è preferibile non per creare setter per le raccolte (elenchi, serie). Creare solo il getter e deselezionare la collezione restituita da esso, vale a dire:

    team.getUserTeamRoles().clear();

  2. Un'altra cosa è che ti manca orfano eliminazione (cioè cancellare oggetto figlio quando viene rimossa dalla raccolta nel genitore.). Per abilitarlo, è necessario aggiungere @OneToMany(orphanRemoval=true) all'entità proprietaria.

+2

Sì, il clear + orphanRemoval ha fatto il trucco. Molte grazie! – AndaP

+0

@Adam Dyga Hibernate noob qui, potresti spiegare di più sul perché è meglio non creare setter per le collezioni? – Jonathan

+0

@Jonny prova a sostituire una raccolta in un'entità con una nuova (ad esempio, nuova ArrayList()) e guarda cosa succede su save;) –