2009-09-06 23 views
4

這是一個設計模式問題。這裏是場景: 我使用EJB3.0和JPA。例如,假設我有一個可以屬於組的用戶。所以在我的用戶實體中,我有一個方法getGroups(),它可以延遲地獲取組。我有一個userDAO的是它有一個方法無狀態會話bean
用戶的getUser(INT UID)在我的JSF支持bean組合JPA,EJB和JSF託管bean的首選設計模式是什麼?

現在我注入的UserDAO的遠程接口,並調用它的getUser得到用戶bean。但是我無法訪問user.getGroups,因爲它是一個分離的實體。所以我可以在這裏想到三種方法:

  1. 在我的dao方法中,我也熱切地獲取組,以便它們也可以在遠程用戶實體中訪問。但與此相關的問題是,團體本身可能會懶惰地取得關係,那些我也不得不急於取得,那些可能有更懶惰的取得關係等等。所以我最終會發送一個重量很大的物體,這些物體大部分屬於我不需要的。
  2. 我發送用戶,因爲它是和依靠我的客戶端不能調用它的getGroups。我可以在UserDAO的是
    列表<整數> getGroupsIds(INT用戶id)
    提供一個單獨的方法和我有也有類似的方法GroupDao getGroup(INT的groupId)等方法偷懶關係的IDS。

  3. 第三種選擇是不發送這些JPA實體,並創建其他POJO,如UserInfo,GroupInfo等,它們只包含每個實體的基本屬性並將它們發送出去。而且我可以在DAO的方法來獲取這些實體像不同的關係:
    列表<的GroupInfo > getGroupsForUser(INT UID)
    列表<的UserInfo > getUsersInGroup(INT GID)

所以哪些是首選模式。還是有一些其他人在這裏使用的模式?

+3

我懷疑的最簡單的方法順利整合這些是使用Seam:http://www.jboss.com/products/seam/ – skaffman

+0

呀從什麼小我知道煤層可能是目前最好的辦法,但我我堅持不使用Seam –

+0

你是在一個特定的JPA實現,或只是問一般。 EclipseLink和Kodo都將按需加載這些內容。或者開發人員可以請求進行一次熱切的獲取。 –

回答

0

我有我的當前項目已經實施的第三個選項。這不好。每次你必須改變2-3班而不是一班。字段重複等。沒有選擇。

如果你真的不需要所有的信息,用戶對象可以熱切地獲取比第二個選項。

如果事實證明您確實需要所有的用戶信息。沒有其他人通過遠程服務使用您的用戶對象,然後使用您的用戶對象 - 與第一個一起去。

在那裏的另一個解決方案。我也需要更好的一個。

+0

第二種方法的問題是,我依靠我的客戶進行危險的正確呼叫。客戶端不知道它不應該調用getGroups。 –

+0

從公共訪問中刪除getGroups()。 –

+0

我認爲這是JPA(休眠)卡住的地方。聽起來很棒,但實際上你不能使用任何酷炫的功能。 –

1

還有第四和第五選項:-)

4)包括對有關的API調用,例如一個「充氣水平」參數getUser(id,inflationLevel)。因此,您將委派負責選擇通過電線發送的對象的哪些部分可供使用該對象的客戶端使用。你可以說所需的調用級別爲粗粒度或細粒度。一個典型的例子就像BASIC(只有直接屬性被填充),ASSOCIATIONS(基本+直接集合/關聯),FULL(整個層次 - 所有關聯對象)。

5)你可以寫你自己的代理,將支持通過線路延遲初始化。這種方法只有在您的延遲加載的關聯對象(或屬性)可能很大但很少被客戶端使用時纔是可行的。

然後,當然,還有縫爲skaffman :-)

0

提到爲什麼用戶實例分離?如果您真的在使用JPA,則可以使用活動實例。因此,當getGroups()將被調用時,用戶組將被延遲加載。

+0

它是分離的,因爲在EJB容器管理的事務中,事務在退出EJB方法時結束,從而銷燬持久化上下文並分離它管理的所有實體。 –

+0

這取決於。在文檔中只有一小部分: 「在Java EE環境中,使用jta-data-source和non-jta-data-source元素 來指定JTA和/或非JTA數據源的全局JNDI名稱被持久性 供應商使用。「 –