2012-01-12 4 views
6

Sono molto nuovo per Spring e sto cercando di far funzionare una relazione molti-a-molti come mi aspetto. Le relazioni funzionano bene, le tabelle vengono create e i dati sono inseriti correttamente. Quello che mi aspetto è che quando svuoto un elenco (ad esempio, svuoto gli "utenti" di ArrayList da un oggetto di tipo "Gruppo"), mi aspetto che il sistema rimuova le relazioni dal database, ma non lo fa.Spring + JPA many to many relationship

Ho le seguenti classi:

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

    ... 
} 

Ecco i DAO:

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

Ecco il metodo di prova:

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

sto facendo qualcosa di sbagliato o è qualcosa non è possibile fare?

Qualsiasi suggerimento è molto apprezzato.

Grazie!

+0

hai provato ad aggiungere 'delete-orphan' al tuo attributo' a cascata '? – fasseg

+0

Hai dichiarato 'IdTransferringMergeEventListener'? – axtavt

+0

Non so se questa è la causa del problema, ma il metodo di salvataggio non dovrebbe restituire void. Dovrebbe restituire il risultato della chiamata di fusione. Prova a fare questa modifica e usa il gruppo restituito: 'g = groupDao.save (g);' –

risposta

2

Ho riletto la tua domanda, e ora la risposta è chiara. Crea un gruppo g e salvalo. Ma poiché il metodo di salvataggio utilizza merge e non si tiene conto del valore restituito da merge per assegnarlo a g, si continua a unire il gruppo di transitori g, che non ha mai assegnato alcun ID. Quindi, ogni volta che viene chiamata la fusione, in realtà si crea un nuovo gruppo anziché modificare quello precedentemente creato.

Modificare il metodo Save per

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

e riassegnare sempre il risultato di g:

g = groupDao.save(g); 

Naturalmente, lo stesso deve essere fatto per l'utente.

+0

Grazie mille molto, questo ha risolto il problema! – satoshi

0

stai rimuovendo solo gli utenti dal gruppo, non è sufficiente. è necessario rimuovere tutti gli utenti dal gruppo e rimuovere quel gruppo dall'elenco di tutti quei gruppi di utenti.

+0

Non dovrebbe essere necessario, dal momento che il lato proprietario è il gruppo. –

+0

sei sicuro? dopo tutto è molto più di una volta. satoshi, puoi per favore provarlo! devo ammettere che non l'ho provato prima:/ – davogotland

+0

Sì, ne sono sicuro. La documentazione dice: "Se l'associazione è bidirezionale, una parte deve essere il proprietario e una parte deve essere l'estremità inversa (cioè verrà ignorata durante l'aggiornamento dei valori della relazione nella tabella di associazione):" –