2014-03-01 28 views
1

簡版:OneToMany與Java的最佳做法

可以說我有一對多的關係,在父母和子女之間。現在在Java代碼中,讀取父對象(從數據庫中獲取它)的最佳實踐是,並在其中應用一種名爲addChild的方法,或者直接創建一個孩子並堅持它,而不必閱讀Parent?

龍版

比方說我們有這樣的父母與子女(從http://en.wikibooks.org/wiki/Java_Persistence/OneToMany

@Entity 
public class Employee { 
    @Id 
    @Column(name="EMP_ID") 
    private long id; 
    ... 
    @OneToMany(mappedBy="owner") 
    private List<Phone> phones; 
    ... 
} 


@Entity 
public class Phone { 
    @Id 
    private long id; 
    ... 
    @ManyToOne(fetch=FetchType.LAZY) 
    @JoinColumn(name="OWNER_ID") 
    private Employee owner; 
    ... 
} 

現在認爲我有一個網頁,員工可以添加電話號碼。所以我已經有了父Employee的id,但是我沒有完整的Employee對象。

1-我從數據庫中獲取整個Employee對象(當然是通過JPA映射)。然後我應用方法employee.addPhone(電話電話)或類似的東西。這導致兩個查詢。

2-我創建了電話對象,並且一個錯誤的員工對象只包含員工的ID,而我堅持?

這是什麼最佳實踐?

回答

3

最好的做法是維護協會的雙方。這可以確保你沒有使用不一致的對象圖。但是,它可能會降低服務的性能,尤其是在創建鏈接到員工的新電話時。事實上,它會加載員工和所有現有電話的狀態。

請注意,JPA只關心該關聯的所有者一方:設置新電話的僱員足以讓該關聯在數據庫中創建。

如果您選擇使用第二種解決方案,您不應該創建一個虛假的Employee對象。而應該從EntityManager的得到員工參考:

Employee e = em.getReference(Employee.class, employeeId); 
Phone phone = new Phone(); 
phone.setEmployee(e); 
em.persist(phone); 

getReference()不產生任何SQL查詢。它返回一個未初始化的代理,這就是你所需要的。優點是,如果方法變得更加複雜,並且調用員工的任何方法,那麼員工的實際狀態將被加載。

+0

謝謝,但如果由getReference返回的員工未初始化,那麼它可能完全不存在?我的意思是實體經理可以返回一個不存在的員工? – ilyes90

+0

是的,由於違反了外鍵約束,您在保存手機時會發生異常。與get()一起做也不例外:em只會在員工存在的情況下才會返回,但另一個事務可能會很好地刪除剛從數據庫加載的員工。外鍵約束是保證一致性的原因。 –

+0

謝謝,現在很清楚。看起來getReference()可以像find()那樣完成工作,並且性能更好。然而,在你的回答中,我明白find()是更好的做法。那是對的嗎 ? – ilyes90