4.1.4 對象身份的範圍

 

作爲開發人員,我們使用==來識別一個對象的身份。因此,如果一個對象更改了狀態以後,它的身份是否仍然和原來一樣?在分層的程序當中,可能並不如此簡單。

爲了更深入探討這個問題,需要明白在java對象身份和數據庫標識之間的關係。有些時候,它們是等價的,而有時它們又不是相等的。我們把這個問題歸結爲對象身份的範圍。

對於這個範圍,有三種一般的選擇:

(1)如果一個持久層沒有身份標識的範圍的話,那麼就無法保證同一行數據被訪問兩次,不同的訪問會返回同一個Java對象。這將帶來問題:如果程序修改了代表同一行數據的兩個不同對象,會造成狀態的不一致。

(2)使用了transaction-scoped的身份標識的持久層能夠保證在單一的事務中,只有一個對象實體能夠代表一個特定的數據行。這就避免了剛纔提到的問題,同時能夠在事務級提供一定的緩存能力。

(3)Process-scoped則更進一步,在每個JVM中保證只有一個對象實體代表同一行數據。

對於典型的web或者商務程序,transaction-scoped是一個很好的選擇。而Process-scoped提供了一些其他的好處包括緩存的使用以及在多個事務中對象實體的重用。但是,在多線程的環境中,程序同步會帶來性能上的消耗。因此,在多線程環境中,每個線程只和那些屬於其自身的持久化實體打交道。

Hibernate使用的是transaction-scoped。實際上,Hibernate的身份標識範圍是Session實例,因此如果使用一個Session的話,那麼能夠保證對象的同一性。但是,Session並不代表是同一個事務。我們將在接下來的部分討論這個概念。讓我們重新把注意力回到持久化生命週期以及身份標識範圍上。

如果你在同一個Session中請求了兩次使用同一數據庫標識的對象,那麼返回的結果將是兩個指向內存同一個對象的不同引用。下面的代碼示例將展示這種行爲,通過在不同的Session中使用load()方法。

當在同一個Session中的時候,對象a和b不僅僅擁有同一個數據庫標識,它們也擁有同一個Java對象標識。一旦超越這個邊界,Hibernate則無法保證Java對象標識的相同性。因此,a和b2並不相等。但是關於數據庫標識的驗證,a.getId().equals(b2.getId())仍然會返回true。

要進一步討論身份標識範圍的問題,我們需要考慮當對象超出其身份標識範圍的時候,持久層如何處理指向對象的引用。例如,對於Hibernate來說,是否允許一個引用指向detached對象。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章