2011-05-14 65 views
1

我需要一些關於在Java中設計N層系統的「集成層」的建議。此層負責持續並檢索「業務層」(位於單獨的服務器上)的數據。我是J2EE新手,我已經閱讀了幾本書和博客。技術首字母縮略詞的字母表讓我很困惑,所以我有一些問題。集成層與業務層的接口如何?

首先,我到目前爲止:我正在使用JPA(通過Hibernate)來持久化和檢索數據到數據庫。我製作了我的數據訪問對象EJB,並計劃部署到應用服務器(JBoss),這使得事務更輕鬆(它們處於我的DAO的功能級別),我不必擔心獲取EntityManager的句柄依賴注入)。以下是一個示例:

@Entity 
class A{ 
    @Id 
    Long id; 
    @OneToMany 
    List<B> setOfBs = new ArrayList<B>; 
} 

@Entity 
class B{ 
    @Id 
    Long id; 
} 

@Remote 
public interface ADAO{ 
    public A getAById(Long id); 
} 

@Stateless 
class ADAOImpl implements ADAO{ 
    @PersistenceContext 
    EntityManager em; 

    public A getAById(Long id){ ... } 
} 

我的問題:業務層應該如何與Integration Tier交換數據。我閱讀過RESTful服務,它們看起來很簡單。我擔心的是當get和set的頻率增加時(HTTP通信似乎並不特別快)。另一個選擇是RMI。我的DAO已經是EJB了。我可以讓業務層直接訪問它們(通過JNDI)嗎?如果是這樣,如果上面示例中的@OneToMany鏈接被延遲加載,會發生什麼?

例如,如果業務層做類似如下:

Context context = new InitialContext(propertiesForIntegrationTierLookup); 
ADAOImpl aDao = (ADAOImpl) context.lookup("something"); 
A myA = aDao.getAById(0); 
int numberOfBs = myA.setOfBs.size(); 

如果setOfBs名單延遲加載,當業務層(一個單獨的服務器上)訪問列表,是大小是否正確?通過EJB的魔力,列表是否能夠正確加載?如果沒有(我期望),解決方案是什麼?

對不起,很長的文章。就像我剛纔說的,我是J2EE新手,並且已經閱讀了足夠的內容以獲得一般想法,但是我需要幫助將這些部分合併到一起。

回答

0

當您在lazy collection上調用size()時,它會被初始化,所以無論您使用哪個接口 - 遠程或本地,您都將獲得正確的大小。

另一種情況是當您嘗試使用JPA類作爲數據傳輸對象(DTO)並通過遠程接口請求它們時。我不記得這裏有任何懶惰的初始化問題,因爲在傳輸之前,所有對象都必須在服務器端序列化(初始化爲懶惰集合)。結果,整個對象圖都通過網絡傳遞,這可能會導致嚴重的CPU和網絡開銷。此外,爲了使反序列化成爲可能,您將必須與遠程應用程序共享JPA類。這就是'EJB魔法'結束的地方和方式:

因此,一旦遠程調用成爲可能,我建議開始考慮將數據傳輸策略和非JPA數據傳輸對象作爲附加數據層。就我而言,我已經註釋了DTO類的XML綁定(JAXB)並在Web服務中重用了它們。

+0

我接受了您的意見,並花了最近幾天研究EE設計模式。看起來我有兩種選擇在集成層和業務層之間傳輸數據:DTO或REST。 使用DTO似乎會在集成層上引入大量額外代碼(從Doman類A轉換爲DTO B等),但DTO可以在業務層中重用。 對於集成層來說,REST很容易,但業務層必須執行解析和性能的繁瑣工作可能是一個問題。這兩種解決方案都不是完美的 有第三種選擇嗎? – Quicksilver 2011-05-16 21:35:59

+0

哎呀,我不是說REST。這兩個選項將是DTO或一些基於文本的方法,如XML。 – Quicksilver 2011-05-17 00:14:29

0

簡短回答:如果您使用的是「集成層」方法,那麼您應該整合的東西應該是鬆散耦合的服務,遵循SOA原則。

這意味着您不應該允許遠程調用可能調用另一臺服務器上的蓋子下的框架的實體的方法。如果你這樣做,你真的構建了一個緊密耦合的分佈式應用程序,你將不得不擔心延遲加載問題和持久化上下文的範圍。如果你想這樣做,你可能會考慮擴展持久化上下文http://docs.jboss.org/ejb3/docs/tutorial/extended_pc/extended.html

您已經談到了「業務層」,但JPA並未提供業務層。它提供實體並允許CRUD操作,但這些通常不是業務操作。 「註冊用戶」操作不僅僅是持久化「用戶」實體的問題。您的DAO層可能提供更高級別的操作,但DAO通常用於在數據庫上放置一個精簡層,但它仍然非常以數據爲中心。

更好的方法是定義業務服務類型操作並將這些操作提供給您公開的服務。您可能需要在DAO之上添加另一個圖層,或者您可能需要一層(轉換DAO圖層)。

您的業務層應調用flush並處理任何JPA異常並隱藏調用者的所有異常。

如何傳輸數據的問題依然存在。在許多情況下,您的業務服務請求的參數與您的JPA實體類似,但我認爲您會注意到,您經常想要定義新的DTO的差異足夠大。例如,「註冊用戶」業務操作可能會同時更新「用戶」和「電子郵件地址」表。用戶表可能包含「createdDate」屬性,該屬性不屬於「RegisterUser」操作的一部分,但設置爲當前日期。

要創建DTO,您可能會喜歡看Project Lombok。

要將DTO複製到實體中,可以使用Apache Commons BeanUtils(例如PropertyUtils.copyProperties)來完成很多腿部工作,如果屬性名稱相同,則可以使用該工作。

就我個人而言,在這種情況下,我沒有看到XML的要點,除非您想徹底解耦您的實現。