2012-11-05 92 views
6

我的問題是非常相似這一個Hibernate Bi-Directional ManyToMany Updates with Second Level cache休眠雙向多對多關聯創建副本

我有類如下圖所示

@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
@Entity 
public class A{ 
    private int id; 
    private List<B> listB; 

    ... 
    @Cache (usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity = B.class) 
    @JoinTable(name = "A_B", joinColumns = { @JoinColumn(name = "a_id") }, 
     inverseJoinColumns = { @JoinColumn(name = "b_id") }) 
    public List<B> getListB() { 
     return listB ; 
    } 
} 

@Cache (usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
@Entity 
public class B{ 
    private int id; 
    private List<A> listA; 

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity = A.class) 
    @JoinTable(name = "A_B", joinColumns = { @JoinColumn(name = "b_id") }, inverseJoinColumns = { @JoinColumn(name = "a_id") }) 
    public List<a> getListA() { 
     return listA ; 
    } 

    public void addToA(A a) { 
     a.getListB().add(this); 
    } 
} 

正如預期的那樣在一個多對多的關係,我我們一直在更新雙向關係的雙方。

現在我面對的問題是,當我嘗試添加/更新集合中的項目時彈出重複條目。下面是我用堅持實體的代碼...

b.getA().clear() ; 
... 
... 
b.getListA().add(A) ; 
b.addToA(A) ; 
em.saveOrUpdate(b) ; 

以下是這是從日誌中獲得通過休眠射出的查詢。

delete from A_B where b_id=? 

insert into A_B (b_id, a_id) values (?, ?) 
insert into A_B (b_id, a_id) values (?, ?) 

delete from A_B where a_id=? 

insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 

我在哪裏錯了? 如何擺脫正在插入的重複項? 緩存正在被正確刷新,但重複條目是唯一的問題!

回答

10

這是一個經典!

問題是,你的映射都是所有者,當一個應該是所有者時,一個應該是相反的。因爲兩者都是所有者,所以對這兩者的更改都會導致插入數據庫;有一個所有者和一個反向,只有一組插入。

你應該能夠改寫B::getListA爲:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "listB") 
public List<A> getListA() 

而且所擁有的一切工作。

請注意,只有擁有方爲@JoinTable註釋。通常,數據庫的任何給定位都映射到正好一個位置在JPA應用程序中。如果你發現自己映射了兩次,請仔細觀察,看看是否有更好的方法來做到這一點。

順便說一句,你不需要targetEntity屬性; JPA提供者可以從泛型中解決這個問題。

+3

太棒了!因此,通過mappedBy屬性,我們通知Hibernate通知所有者表和實體的連接配置。我的理解是否正確? – Venkat

+2

是的,就是這樣。 –

+0

任何想法爲什麼你可能仍然會得到重複插入,當你已經正確映射設置?在我的情況下,我正在使用字段訪問而不是方法訪問​​。這可能是一個問題嗎? – JBCP