2009-08-19 29 views
5

Ich habe 2 Entitäten: User und UsersList.Hibernate @ManyToMany löschen 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; 
    } 
} 

und

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

und Code wie diese:

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

wo

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

In Schritt 1 Ich habe 3 Zeilen in dem Benutzer (USER_ID) Tabelle .

Nach Schritt 2 (zweiter Kommentar) habe ich 1 Zeile in der Tabelle USERS_LIST (USERS_LIST_ID) und in der Join-Tabelle USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 3 Zeilen.

Was ich in Schritt 3 erreichen möchte, ist folgender: Wenn ich einen Benutzer aus der Tabelle USERS - sagen wir Benutzer mit USER_ID = 4 lösche, möchte ich nur die Zeile mit USER_ID = 4 aus der Join-Tabelle löschen und die anderen bleiben.

Gibt es eine Annotationslösung für mein Problem?

+0

Wie sieht die Methode deleteWithHibernate aus? –

Antwort

-1

Ich glaube, Sie müssen diese annotaion

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

und Änderung cascade.remove zu CascadeType.ALL Ihren Code so etwas wie das, was Sie

@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 ist eine Hibernate-spezifische Annotation und in JPA nicht verfügbar. – Mohsen

9

sein müssen, ist das Attribut @JoinTable :

Hibernate weiß nicht, dass sich die Viele-zu-Viele-Beziehungen gegenseitig betreffen, und erstellt wahrscheinlich zwei Join-Tabellen. Wenn Sie dieselbe @JoinTable auf beiden Seiten der Beziehung angeben, funktioniert sie wie erwartet.

Stellen Sie sicher, dass die JoinColumn und die inverseJoinColumn Gegensätze auf den gegenüberliegenden Seiten der Beziehung sind.

  • joinColumn auf der einen Seite == inverseJoinColumn auf der anderen Seite
  • inverseJoinColumn auf der einen Seite == joinColumn auf der anderen Seite

Ich hoffe, das hilft.

@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

Ich verwende "@JoinTable" in meiner Lösung, kann aber die Zeilen nicht löschen. Ist es notwendig, alle Kaskaden zu erwähnen, die Sie erwähnt haben? – Logan

+1

das OP verwendet 'mappedBy', ist das nicht genug für den Winterschlaf um zu wissen, wie das' @ JoinTable' aussehen soll? Das explizite Auflisten des '@ JoinTable'-Namens und der Spalten scheint ein wenig überflüssig, es sei denn, Sie möchten wirklich sicherstellen, dass Ihre genauen Namen verwendet werden. – fommil

+0

Große Lösung! – kinkajou

Verwandte Themen