2012-01-12 22 views
6

私はSpringには新しく、多対多の関係を期待しています。関係は正常に動作し、テーブルが作成され、データが正しく挿入されます。私が期待しているのは、リストを空にする(つまり、 "Group"タイプのオブジェクトからArrayListの "users"を空にする)、システムはデータベースから関係を削除することを期待します。Spring + JPA多対多の関係

私は次のクラスがあります。

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

    ... 
} 

はDAOを以下のとおりです。

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

私が何か間違ったことか、それは午前:ここ

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

は、試験方法でありますすることができない何か?

いずれのヒントも本当に感謝しています。

ありがとうございました!

+0

カスケード '属性'に 'delete-orphan'を追加しようとしましたか? – fasseg

+0

'IdTransferringMergeEventListener'を宣言しましたか? – axtavt

+0

これが問題の原因であるかどうかはわかりませんが、saveメソッドはvoidを返すべきではありません。マージコールの結果を返す必要があります。この変更を行い、返されたグループを使ってみましょう: 'g = groupDao.save(g);' –

答えて

2

質問が再読されました。答えは明らかです。グループgを作成して保存します。しかし、保存メソッドがmergeを使用していて、に割り当てるためにmergeによって返された値を考慮に入れていないと、決してIDが割り当てられていない過渡グループgをマージし続けることになります。したがって、マージが呼び出されるたびに、以前に作成されたグループを変更するのではなく、新しいグループを実際に作成します。

変更は

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

にメソッドを保存し、常にgに結果を再割り当て:もちろん

g = groupDao.save(g); 

は、同じことがユーザーのために行われなければなりません。

+0

ありがとう多く、これは問題を解決しました! – satoshi

0

グループからユーザーを削除するだけでは、それだけでは不十分です。グループからすべてのユーザーを削除し、そのグループのすべてのユーザーのグループからそのグループを削除する必要があります。

+0

所有側がグループなので、これは必要ではありません。 –

+0

本当ですか?結局のところ、それは数多くある。さとし、これを試してみてください!私はまずそれをテストしなかったことを認めなければなりません:/ – davogotland

+0

はい、確信しています。ドキュメントは次のように言っています: "関連が双方向である場合、一方の側は所有者でなければならず、一方の側は反対側の端でなければなりません(つまり、関連テーブルの関係値を更新するときに無視されます):" –