2013-12-21 104 views
9

在一對多的JPA關聯中,初始化關係爲空集合被認爲是最佳實踐嗎?例如。初始化或不初始化JPA關係映射?

@Entity 
public class Order { 

    @Id 
    private Integer id; 

    // should the line items be initialized with an empty array list or not? 
    @OneToMany(mappedBy="order") 
    List<LineItem> lineItems = new ArrayList<>(); 

} 

在上面的例子是它更好地與空ArrayList與否的默認值定義lineItems?優缺點都有什麼?

回答

13

JPA本身並不關心集合是否被初始化。使用JPA從數據庫中檢索訂單時,JPA將始終返回具有OrderLines非空列表的訂單。

原因:因爲一個訂單可以有0,1或N行,並且最好使用空白,一個大小或N大小的集合建模。如果集合爲空,則必須檢查代碼中的任何地方。例如,這個簡單的循環會導致一個NullPointerException如果列表爲空:

for (OrderLine line : order.getLines()) { 
    ... 
} 

所以,最好使通過始終具有非空的集合,即使是實體的新創建的實例不變。這使得生產代碼創建新訂單更安全,更清潔。這也使得你的單元測試,使用不是來自數據庫的Order實例,更安全,更清潔。

2

我也建議使用番石榴的不可變的集合,例如,

import com.google.common.collect.ImmutableList; 
// ... 
@OneToMany(mappedBy="order") 
List<LineItem> lineItems = ImmutableList.of(); 

這個成語從來沒有創建一個新的空單,但重用代表空列表的單個實例(類型並不重要)。這是函數式編程語言(Scala也這樣做)的一種非常常見的做法,並且將空對象而不是空值的開銷減小到零,從而使得對成語模擬的任何效率論點成爲可能。

+0

感謝您的有用評論。 – cripox

+1

但是,在JPA實體的情況下,我會爭辯說,您應該使用_mutable_列表進行初始化,將該字段設置爲私有,並且只爲您的集合提供公共getter。只有這樣,你才能確定,'lineItems'永遠不是'null'。我不擔心創建空列表,因爲現代JVM對於垃圾收集非常有用。作爲一般說明:永遠不要預先優化您的代碼! –

+0

我同意@StefanHaberl,你不應該用一個不可變的集合初始化實體字段。這將使創建實體和測試的新實例變得困難。如果你擔心性能,你可能會嘗試像'new HashSet <>(0)'(https://stackoverflow.com/questions/18076492/why-initialize-hashset0-to-zero)。 – csharpfolk