2012-01-12 31 views
6

Soy muy nuevo en Spring y estoy tratando de hacer que una relación de muchos a muchos funcione como espero. Las relaciones funcionan bien, las tablas se crean y los datos se insertan correctamente. Lo que espero es que cuando vacíe una Lista (es decir, vacíe los "usuarios" ArrayList de un objeto de tipo "Grupo"), espero que el sistema elimine las relaciones de la base de datos, pero no es así.Spring + JPA relación muchos a muchos

Tengo las siguientes clases:

@Entity 
@Table(name = "`group`") 
public class Group 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    private int id; 

    @Column(name = "name") 
    private String name; 

    @ManyToMany(cascade = {CascadeType.ALL}) 
    @JoinTable(
      name = "`user_has_group`", 
      joinColumns = @JoinColumn(name = "group_id", referencedColumnName = "id"), 
      inverseJoinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id") 
    ) 
    private List<User> users = new ArrayList<User>(); 

    ... 
} 

@Entity 
@Table(name = "`user`") 
public class User 
{ 
    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    private int id; 

    @Column(name = "name") 
    private String name; 

    @ManyToMany(mappedBy = "users") 
    private List<Group> groups = new ArrayList<Group>(); 

    ... 
} 

Éstos son los DAOs:

@Repository 
public class GroupJpaDao implements GroupDao 
{ 
    private EntityManager em; 

    @Transactional 
    public void save(Group group) 
    { 
     this.em.merge(group); 
    } 

    ... 

    @PersistenceContext 
    void setEntityManager(EntityManager entityManager) 
    { 
     this.em = entityManager; 
    } 
} 

@Repository 
public class UserJpaDao implements UserDao 
{ 
    private EntityManager em; 

    @Transactional 
    public void save(User user) 
    { 
     this.em.merge(user); 
    } 

    ... 

    @PersistenceContext 
    void setEntityManager(EntityManager entityManager) 
    { 
     this.em = entityManager; 
    } 
} 

Aquí es el método de ensayo:

@Test 
public void test() 
{ 
    Group g = new Group(); 
    g.setName("Test group"); 
    groupDao.save(g); // Works fine - inserts the group into the database 

    User u = new User(); 
    u.setName("Test user"); 
    userDao.save(u); // Works fine - inserts the user into the database 

    g.addUser(u); 
    groupDao.save(g); // Works fine - adds the many-to-many relationship into the database 

    g.removeAllUsers(); 
    groupDao.save(g); // Doesn't work - I'm expecting it to remove all the related relationships from the database but it doesn't! 
} 

estoy haciendo algo mal o es algo que no es posible hacer?

Cualquier pista es muy apreciada.

¡Gracias!

+0

¿Intentó agregar 'delete-orphan' a su atributo' cascada'? – fasseg

+0

¿Has declarado 'IdTransferringMergeEventListener'? – axtavt

+0

No sé si esa es la causa del problema, pero el método de guardar no debe volverse vacío. Debería devolver el resultado de la llamada de combinación. Intente hacer este cambio y utilizando el grupo devuelto: 'g = groupDao.save (g);' –

Respuesta

2

He vuelto a leer su pregunta, y ahora la respuesta es clara. Cree un Grupo g y guárdelo. Pero como su método de guardar usa merge, y no tiene en cuenta el valor devuelto por merge para asignarlo al g, sigue fusionando el grupo transitorio g, que nunca tiene ninguna ID asignada. Por lo tanto, cada vez que se invoca fusión, en realidad se crea un nuevo grupo en lugar de modificar el creado previamente.

Cambie el modo de salvar a

public Group save(Group group) 
{ 
    return this.em.merge(group); 
} 

y siempre reasignar el resultado a g:

g = groupDao.save(g); 

Por supuesto, el mismo debe ser hecho para el usuario.

+0

Muchas gracias mucho, esto resolvió el problema! – satoshi

0

solo está eliminando a los usuarios del grupo, eso no es suficiente. debe eliminar todos los usuarios del grupo y eliminar ese grupo de la lista de grupos de todos los usuarios.

+0

No debería ser necesario, ya que el lado propietario es el grupo. –

+0

¿estás seguro? es manytomany después de todo. satoshi, ¿puedes probar esto? Debo admitir que no lo probé primero:/ – davogotland

+0

Sí, estoy seguro. La documentación dice: "Si la asociación es bidireccional, un lado tiene que ser el propietario y un lado tiene que ser el extremo inverso (es decir, se ignorará al actualizar los valores de relación en la tabla de asociación):" –

Cuestiones relacionadas