4

我想模擬JPA/Hibernate兩個實體之間的關係,一個組和一個帳戶。一個帳戶可以有多個組,但反之亦然,所以我們在帳戶和組之間有OneToMany關係。 我的工作同事建議到實體AccountGroup模擬像如何在構建hibernate實體時處理雙向關係?

public class Account { 
    private List<Group> groups = new ArrayList<Group>(); 

    public Account() {} 

    public void setGroups(List<Group> usergroups) { 
     this.groups = groups; 
    } 

    @OneToMany(mappedBy = "account") 
    public List<Group> getGroups() { 
     return groups; 
    } 
} 

public class Group { 
    private String name; 
    private Account account; 

    public Group() {} 

    public Group(String name, Account account) { 
     this.name = name; 
     addToAccount(account); 
    } 

    public void addToAccount(Account account) { 
     setAccount(account); 
     List<Group> accountGroups = account.getGroups(); 
     accountGroups.add(this); 
    } 

    @ManyToOne 
    public Account getAccount() { 
     return account; 
    } 

    public void setAccount(Account account) { 
     this.account = account; 
    } 
} 

我現在的問題是關於輔助方法addToAccount中的Group構造函數的用法。根據我的同事的說法,這種方法是必要的,因爲我們需要更新雙方兩個實體之間的雙向關係,以確保兩個實體的一致的存儲模型。

不過,我相信調用構造函數的方法addToAccount是不是一個好主意,因爲

  1. ListGroup的s是懶洋洋地 牽強,所以調用該方法 addToAccount需要一個開放的 交易。因此, Group的構造函數只能在 打開的事務中調用。在我看來,這是一個非常煩人的限制。

  2. 給出作爲參數 到的Group構造函數的Account對象 由構造改變。在我看來,這是構造函數令人驚訝的副作用,不應該發生。

我的建議是爲了更好地使用一個簡單的構造像

public Group(String name, Account account) { 
      this.name = name; 
      this.account = account; 
     } 

和與雙向關係手動處理。但也許我錯了。在構建hibernate實體時,人們應該如何處理雙向關係?

+0

我確實認爲這是不好的做法,你的大學提出了什麼。不只是大約1或2(特別是2!),高於你應該在構造函數中使用可重寫的方法,因爲它可能在子類中被有效地覆蓋,並且在子對象構造函數被調用!之前被調用。我相信你應該保持一個一致的對象圖(內存模型),我正在研究如何最好地做到這一點,並通過這個..並且不能得到靜音!你最終得到答案嗎? – Victor

回答

0

根據我的經驗,您完全按照通常的做法進行操作。我的問題是關於爲什麼你想直接從集團操縱賬戶的結構(我預計還會有比上面提供的樣本更多)。

我還質疑這是OneToMany還是ManyToMany的情況(通常多個帳戶可以屬於一個組,並且多個組可以屬於一個帳戶,但它全部在特定會計方案的語義中...... )無論如何:你做得很對,儘管我質疑(在這種情況下)你爲什麼要直接操縱該賬戶(除非它是懶惰加載的),這完全沒問題。

[您可能需要添加一些級聯規則,以便它堅持正確取決於您的配置。]

你應該注意到,通過映射到帳戶,您已經有效地將其添加到帳戶的列表。當數據庫接下來查詢創建該列表時,它將通過查找來自Account實體的參考來填充列表。

在短期>

public void Group.setAccounts(Account a) 
{ 
    this.account = a; 
} 

實際上等同於你在上面做什麼。該數據庫將查詢和使用的東西類似於填充列表:從延遲加載

//Pseudo SQL 
    SELECT g.id FROM Group g WHERE g.account_id = :account_id 

因此,除了(你可能會或可能不希望)向該組是不必要的,因爲名單是由查詢定義。

(不要把它太硬,它看起來很簡單,我希望長時間的解釋給你什麼在JPA發生的事情的想法)

3

在我們的項目中,我們通常儘量避免雙向關聯。

原因之一是你的模型中有一個循環,如果你想以某種方式序列化它,可能會產生問題,比如我們假設你想序列化一個Account並且你的序列化算法不夠聰明,最後得到一個無限循環(因爲Group有一個參考返回到Account)。

第二個原因是我發現它只有一種方式來導航模型。我通常會做的是刪除Account實體中的OneToMany關聯,並在需要爲特定Account收集所有Group(但這可能取決於您的用例和個人喜好)時使用存儲庫調用。第三,如果你擺脫了addToAccount方法,並且你使用了字段訪問,你可以讓你的類不可變,這是件好事。

相關問題