2009-08-19 5 views
5

J'ai 2 entités: User et UsersList.Hibernate @ManyToMany supprimer la 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; 
    } 
} 

et

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

et le code comme celui-ci:

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

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

Dans l'étape 1 I ai 3 lignes dans la table utilisateurs (USER_ID) .

Après l'étape 2 (deuxième commentaire), j'ai 1 ligne dans la table USERS_LIST (USERS_LIST_ID) et dans la table de jointure USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 3 lignes. Ce que je veux atteindre à l'étape 3 est la suivante: quand je supprime un utilisateur de la table USERS - disons user avec USER_ID = 4, je veux juste la ligne avec USER_ID = 4 de la table de jointure à supprimer et les autres à rester.

Existe-t-il une solution d'annotation à mon problème?

+0

À quoi ressemble la méthode deleteWithHibernate? –

Répondre

-1

Je pense que vous devez que ce annotaion

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

et le changement cascade.remove à CascadeType.ALL votre code doit être quelque chose comme ça

@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 est une annotation spécifique hibernate et n'est pas disponible en JPA. – Mohsen

9

Qu'est-ce que vous avez besoin est l'attribut @JoinTable :

Hibernate ne sait pas que les relations plusieurs-à-plusieurs se réfèrent les unes aux autres et créeront probablement deux tables de jointure. Si vous spécifiez le même @JoinTable des deux côtés de la relation, cela fonctionnera comme prévu.

Assurez-vous que les propriétés joinColumn et inverseJoinColumn sont opposées sur les côtés opposés de la relation.

  • joinColumn d'un côté == inverseJoinColumn autre côté
  • inverseJoinColumn d'un côté == joinColumn autre côté

J'espère que cela aide.

@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"), 
      inverseJoinColumns=[email protected](name="Role_id") 
     ) 
    public List<Role> getRoles() { 
     return roles; 
    } 

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

} 
+1

J'utilise '@JoinTable' dans ma solution, mais je n'arrive toujours pas à supprimer les lignes. Est-il nécessaire de mentionner toutes les cascades que vous avez mentionnées? – Logan

+1

l'OP utilise 'mappedBy', n'est-ce pas suffisant pour que hibernate sache à quoi devrait ressembler' @ JoinTable'? La liste explicite du nom et des colonnes de '@ JoinTable' semble un peu superflue, sauf si vous voulez vraiment vous assurer que vos noms exacts sont utilisés. – fommil

+0

Excellente solution! – kinkajou

Questions connexes