實體Bean是持久化對象,它能夠存儲到持久化存儲源中。實體Bean是EJB編程模型中最為重要的利器之一。
將對象映射到RDBMS的技術稱之為對象-關系映射。它能夠實現內存對象同關系數據的相互轉換。O/R映射器能夠將Java對象映射到任意RDBMS模式。比如簡單的O/RMapping引擎能夠將Java類映射成SQL表定義。Java語言提供的對象序列化功能比O/RMapping簡單多了。O/RMapping是更加復雜、成熟的對象持久化機制。通過將Java對象分解成關系數據,應用便能夠查找到所需的數據了。
通過如下兩種方式能夠完成Java對象到關系數據的映射。其一,通過硬編碼實現O/RMapping.其二,借助于O/RMapping產品,自動完成映射過程,比如:Hibernate.
對于任何成熟的、基于OO多層部署的企業應用而言,總可以劃分出2種截然不同的組件類型。1、應用邏輯組件,2、持久化數據組件。會話Bean和實體Bean的最大區別在于實體Bean是實體,客戶是可以看的到的。因此實體Bean能夠獨立于客戶應用的生命周期。對于實體Bean而言,通過比較它們各自含有的數據便能夠區分不同的實體Bean.這意味著客戶能夠引用單個的實體Bean實例并將它傳入到其他應用中,不同的客戶可以共享同樣的實體Bean實例,這對于會話Bean是辦不到的。會話Bean建模過程或者工作流。實體Bean本身就是客戶,它就是持久化狀態對象。
實體Bean實例存在幾方面的含義:
1、持久化數據的Java表示,即它能夠從持久化存儲源裝載數據到內存中。同時,實體Bean實例能夠將裝載到的數據存儲到實例的成員變量中。
2、通過修改內存中的Java對象可以改變數據的取值。
3、還可以將修改后的數據保存到存儲源匯中,從而更新RDBMS中的物理數據。
實體Bean是持久化對象,它能夠長期存在。即使出現了不可恢復的失敗,比如應用服務器癱瘓、數據庫癱瘓,實體Bean還是能夠存活的。原因在于實體Bean只是對底層具有容錯行為的持久化存儲源中數據的映射,因此,即使極其癱瘓,內存中的實體Bean實例還可以重新構建。在極其重啟后,實體Bean實例需要從底層存儲源裝載數據,并使用獲得的數據對實體Bean實例中的各個域進行setter操作。實體Bean比客戶會話的生命周期要長??梢哉J為,數據庫中記錄存活的時間決定了實體Bean實例的生命周期。
相同數據往往存在多分物理拷貝,比如內存中的實體Bean實例、實體Bean數據本身,他們都是對RDBMS中數據的拷貝。因此,EJB容器需要提供某種機制實現數據在Java對象和RDBMS間的自動傳輸。實體Bean的Bean類為此提供了2個特殊方法:
ejbLoad():它能夠從持久化存儲源中讀取數據,并存儲到實體Bean實例的域中。
ejbStore():它能夠將當前實體Bean實例的域值保存到底層RDBMS中。
那么何時需要完成內存中實體Bean實例和RDBMS中數據的傳遞和轉換,開發者需要知道是誰調用了ejbLoad()和ejbStore(),答案是EJB容器。它們是回調方法,供EJB容器調用。EJB規范要求所有的實體Bean組件必須提供它們。至于讀取或存儲數據的時機,由EJB容器決定。依據實體Bean實例當前的事務狀態,EJB容器會自動計算出需要調用實體Bean實例中的ejbLoad(),ejbStore()方法的時機,這也是使用實體Bean組件的優勢之一:開發者不用考慮java對象同步底層RDBMS的問題。
為了滿足大量并發客戶訪問同一數據的要求,架構師需要借助于實體Bean設計出高性能的訪問系統。如下給出一種解決方案:允許多個客戶共享同一實體Bean實例。因此,實體Bean實例能夠同時服務多個客戶。盡管表面上看是可行的,但是對于EJB而言,這是行不通的。原因有亮點:其一,為實現實體Bean實例服務多個并發客戶,必須保證實體Bean實例是線程安全的,開發線程安全的代碼并不是一件容易的工作,而且經常會出現一堆錯我。其二,底層事務系統幾乎不可能控制多個線程的并發執行,事務往往同具體的線程綁定在一起。因此,基于上述理由,單個實體Bean實例只能夠在單線程環境中運行。對于所有的EJB組件而言,包括會話Bean、消息驅動Bean、實體Bean,它們都是以單線程方式運行的。
當然,強制要求各個實體Bean實例只能同時服務單個客戶,將引入性能瓶頸。由于實例以單線程方式運行,客戶需要排隊等候實體Bean實例,從而獲得對實體Bean實例的調用,這對于大型企業應用而言,是不允許出現的
為了提供系統性能,EJB容器會實例化同一實體Bean的多個實例。這使得多個客戶能夠并發同不同實體Bean實例進行交互,而這些實體Bean實例代表了同一RDBMS數據。事實上,這就是EJB容器的運行行為。因此,客戶再也不用排隊等候實體Bean實例,因為存在多個實體Bean實例了。
一旦多個實體Bean實例代表了同一RDBMS數據,則引入了另外一個問題:數據癱瘓。如果多個實體Bean實例代表的數據是通過緩存管理的,則需要在內存中拷貝多分緩存中的數據。顯然,某些緩存中的數據將變得陳舊,因此會出現很多過期的數據。
為了實現實體Bean實例的緩存一致性,各個實體Bean實例必須同底層存儲元進行同步。EJB容器將通過調用ejbLoad(),ejbStore()方法同步這些實體Bean實例。
至于實體Bean實例同底層RDBMS數據的同步頻率,則取決于事務。事務將各個客戶請求隔離起來。借助于事務實現數據同步。
EJB容器提供的實例池是很有意義的。當然,并不是只有實體Bean才存在實例池。在將實體Bean實例重新分配給不同EJB對象時,會存在一些問題,并要求容器去解決。比如當實體Bean實例被指定給EJB對象時,它可能還持有資源(比如Socket連接)。如果將實體Bean實例放置在實例池中,Socket連接不在需要。因此為實現資源的獲取和釋放,實體Bean的Bean類需要實現如下2個回調方法:
1、ejbActivate().在將實體Bean實例從實例池中取出來時,EJB容器會自動調用它。該過程稱之為激活。進而,EJB容器會將實體Bean實例分配給某EJB對象,并同時獲得主鍵對象。在執行ejbActivate()方法期間,實例需要獲得所需的資源,比如Socke,否則,在將實體Bean實例分配給某EJB對象時,無法對資源進行操作。
2、ejbPassivate().在將實體Bean實例放置到實例池中時,EJB容器會調用它。注意,它也是回調方法。這一過程稱之為掛起。進而,EJB容器需要從某EJB對象中取回分配于它的實體Bean實例,并將實例的主鍵對象也收回。在執行ejbPassivate()方法期間,需要釋放ejbActivate()執行期間獲得的相關資源,比如:Socket.
一旦實體Bean實例被掛起,不但要釋放它持有的資源,還將實例的狀態信息保存起來。因此,實體Bean實例最新的狀態信息可以從RDBMS中找到了。為了保存實體Bean實例的域信息到RDBMS中,容器要在掛起實例前調用ejbStore()方法。類似的,一旦實體Bean被激活,不但要獲得所需的資源,還要從RDBMS裝載最新的數據,為了完成數據的讀取,EJB容器將在激活實體Bean實例后調用ejbLoad()方法。
posted on 2009-11-15 11:46
王永慶 閱讀(291)
評論(0) 編輯 收藏 所屬分類:
EJB學習筆記