2009-08-19 29 views
5

Ho 2 entità: User e UsersList.Hibernate @ManyToMany delete relation

@Entity 
@Table(name = "USERS") 
public class User { 
    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @ManyToMany(cascade = CascadeType.REMOVE, mappedBy = "users") 
    private List<UsersList> usersLists = new ArrayList<UsersList>(); 

    public List<UsersList> getUsersLists() { 
     return usersLists; 
    } 

    public void setUsersLists(List<UsersList> usersLists) { 
     this.usersLists = usersLists; 
    } 
} 

e

@Entity 
@Table(name = "USERS_LIST") 
public class UsersList { 
    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @ManyToMany 
    private List<User> users = new ArrayList<User>(); 

public List<User> getUsers() { 
     return users; 
    } 

    public void setUsers(List<User> users) { 
     this.users = users; 
    } 
} 

e codice come questo:

// 1 
List<User> dbUsers; // 3 the user instances are persisted in DB 
UsersList usersList = new UsersList(); 
usersList.setUsers(dbUsers); 

// 2 - now persist the usersList using hibernate... 
saveWithHibernate(usersList); 

//3 - delete using a persisted user 
deleteWithHibernate(dbUsers.get(0).getId()); 

dove

deleteWithHibernate(Long id) { 
     User usr = hibernateTemplate.get(User.class, id); 
     hibernateTemplate.delete(usr); 
} 

Nel passaggio 1 ho 3 righe nel utenti (USER_ID) Tavolo .

Dopo il passaggio 2 (secondo commento) Ho 1 riga nella tabella USERS_LIST (USERS_LIST_ID) e nella tabella di join USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 3 righe.

Quello che voglio ottenere nel passaggio 3 è il seguente: quando elimino un utente dalla tabella UTENTI - diciamo utente con USER_ID = 4, voglio solo la riga con USER_ID = 4 dalla tabella di join da eliminare e gli altri a rimanere.

C'è una soluzione di annotazione al mio problema?

+0

Che aspetto ha il metodo deleteWithHibernate? –

risposta

-1

Penso che tu debba quanto questo annotaion

@OnDelete(action = OnDeleteAction.CASCADE) 
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 

e il cambiamento cascade.remove per CascadeType.ALL il codice deve essere qualcosa di simile

@ManyToMany(cascade = CascadeType.ALL, mappedBy = "users") 
    @OnDelete(action = OnDeleteAction.CASCADE) 
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
    private List<UsersList> usersLists = new ArrayList<UsersList>(); 
+0

@OnDelete è un'annotazione specifica di ibernazione e non è disponibile in JPA. – Mohsen

9

Quello che vi serve è l'attributo @JoinTable :

Hibernate non sa che le relazioni molti-a-molti si riferiscono l'un l'altro e probabilmente creeranno due tabelle di join. Se si specifica la stessa @JoinTable su entrambi i lati della relazione, funzionerà come previsto.

Assicurarsi che joinColumn e inverseJoinColumn siano opposti sui lati opposti della relazione .

  • joinColumn da un lato == inverseJoinColumn sul lato opposto
  • inverseJoinColumn da un lato == joinColumn sul lato opposto

Spero che questo aiuta.

@Entity 
public class Role extends Identifiable { 

    @ManyToMany(cascade ={CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinTable(name="Role_Permission", 
      [email protected](name="Role_id"), 
      [email protected](name="Permission_id") 
     ) 
    public List<Permission> getPermissions() { 
     return permissions; 
    } 

    public void setPermissions(List<Permission> permissions) { 
     this.permissions = permissions; 
    } 
} 

@Entity 
public class Permission extends Identifiable { 

    @ManyToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}) 
    @JoinTable(name="Role_Permission", 
      [email protected](name="Permission_id"), 
      [email protected](name="Role_id") 
     ) 
    public List<Role> getRoles() { 
     return roles; 
    } 

    public void setRoles(List<Role> roles) { 
     this.roles = roles; 
    } 

} 
+1

Sto usando '@JoinTable' nella mia soluzione, ma non riesco ancora a cancellare le Righe. È necessario menzionare tutte le cascate che hai menzionato? – Logan

+1

l'OP usa 'mappedBy', non è abbastanza per ibernare sapere come dovrebbe apparire' @ JoinTable'? Elenca esplicitamente il nome e le colonne di '@ JoinTable' sembra un po 'superfluo, a meno che tu non voglia veramente assicurarti che i tuoi nomi esatti siano usati. – fommil

+0

Ottima soluzione! – kinkajou

Problemi correlati