2009-08-19 15 views
5

Tengo 2 entidades: User y UsersList.Hibernate @ManyToMany eliminar relación

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

y

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

y el código como éste: mesa

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

donde

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

En el paso 1 tengo 3 filas de los usuarios (USER_ID) .

Después del paso 2 (segundo comentario) Tengo 1 fila en la tabla USERS_LIST (USERS_LIST_ID) y en la tabla de combinación USERS_LIST_USERS (USER_ID, USERS_LIST_ID) 3 filas.

Lo que quiero lograr en el paso 3 es el siguiente: cuando elimino un usuario de la tabla USUARIOS - digamos usuario con USER_ID = 4, solo quiero eliminar la fila con USER_ID = 4 de la tabla de unión y los otros a permanecer.

¿Existe una solución de anotación para mi problema?

+0

¿Cómo es el método deleteWithHibernate? –

Respuesta

-1

Creo que se debe ya que esto annotaion

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

y el cambio cascade.remove a CascadeType.ALL su código debe ser algo como esto

@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 es una anotación específica de hibernación y no está disponible en JPA. – Mohsen

9

Lo que necesita es el atributo @JoinTable :

Hibernate no sabe que las relaciones muchos a muchos se refieren entre sí y probablemente creará dos tablas de unión. Si especifica el mismo @JoinTable en ambos lados de la relación, funcionará como se espera.

Asegúrate de que joinColumn y la inversaJoinColumn son opuestos en los lados opuestos de la relación.

  • joinColumn en un lado == inverseJoinColumn en el otro lado
  • inverseJoinColumn en un lado == joinColumn en el otro lado

espero que esto ayude.

@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

Estoy usando '@JoinTable' en mi solución, pero todavía no puedo eliminar las filas. ¿Es necesario mencionar todas las cascadas que has mencionado? – Logan

+1

OP usa 'mappedBy', ¿no es suficiente para que hibernate sepa cómo debe ser el' @ JoinTable'? Indicar explícitamente el nombre y las columnas de '@ JoinTable' parece un poco superfluo, a menos que realmente desee asegurarse de que se usen sus nombres exactos. – fommil

+0

¡Gran solución! – kinkajou

Cuestiones relacionadas