2011-09-21 87 views
4

我有2個JPA實體之間有一個雙向關係。合併JPA實體返回舊值

@Entity 
public class A { 

    @ManyToOne(cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    B b; 

    // ... 
} 

@Entity 
public class B { 

    @OneToMany(mappedBy="b",cascade={CascadeType.PERSIST, CascadeType.MERGE}) 
    Set<A> as = new HashSet<A>(); 

    // ... 
} 

現在我更新分離A其中也有一些Bs反之亦然關係的一些字段值,並通過

public String save(A a) { 
    A returnedA = em.merge(a); 
} 

returnedA現在已經把它合併A在更新之前的值。 我想,

FINEST: Merge clone with references [email protected] 
    FINEST: Register the existing object [email protected] 
    FINEST: Register the existing object [email protected] 
    FINEST: Register the existing object [email protected] 

表明,在B中的引用As(其中仍然有舊值)負責覆蓋新的?

有沒有人有提示如何防止這種情況發生?

任何想法,非常感謝!

在此先感謝。

+1

一個快速的想法:從Bs中刪除合併級聯。 – Thomas

+0

感謝您的建議,@Thomas。這肯定會有所幫助,但不幸的是,由於經常發生雙向更新,我寧願保留它。 – Dirk

+1

不是一個理想的解決方案,但假設你擁有一個包含.save(A a)和.save(B B)的方法,你可以隨時刪除級聯和手動處理級聯.. – rhinds

回答

1

Dirk,我有一個類似的問題和解決方案(我可能不會正確利用API)是密集型的。 Eclipselink維護一個對象緩存,如果它們沒有更新(合併/持久化),數據庫通常會反映更改,但級聯對象不會更新(特別是父節點)。

(我聲明瞭一個作爲記錄連接多個B的) 實體:

public class A 
{ 
    @OneToMany(cascade = CascadeType.ALL) 
    Collection b; 
} 

public class B 
{ 
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.REFRESH}) //I don't want to cascade a persist operation as that might make another A object) 
    A a; 
} 

在上述解決辦法的情況下:

public void saveB(B b) //"Child relationship" 
{ 
    A a = b.getA();//do null checks as needed and get a reference to the parent 
    a.getBs().add(b); //I've had the collection be null 
    //Persistence here 
    entityInstance.merge(a); // or persist this will cascade and use b 
} 

public void saveA(A a) 
{ 
    //Persistence 
    entityInstance.merge(a) // or persist 
} 

你在做什麼這裏是物理從頂部級聯合並鏈。維護令人煩惱,但它確實解決了問題。或者,你可以通過檢查它是否被分離並刷新/替換來處理它,但是我發現它不太理想,並且不適合使用。

如果有人對什麼是正確的設置有更好的答案,我會很樂意聽到它。現在我已經爲我的關係實體採用了這種方法,並且它維護起來令人惱火。

祝您好運,我很樂意聽到更好的解決方案。

+0

感謝單一的中央服務/ DAO類你的回答,這對我來說似乎是一個可行的解決方案。 – Dirk