簡體   English   中英

在視圖模式中打開會話

[英]Open Session In View Pattern

鑒於我選擇的JPA(Hibernate實現),Spring和<插入MVC框架 - 開發框架 - Struts 1,Struts 2,Spring MVC,Stripes ...>,我問這個問題。

我一直在考慮我的實體層中的關系 - 例如我有一個訂單實體,它有許多訂單行。 我已經設置了我的應用程序,因此它急切地為每個訂單加載訂單行。 如果我將獲取策略設置為false,你認為這是解決我會遇到的延遲初始化問題的一種懶惰方法嗎?

我看到它的方式,在檢索實體及其關聯時,我有以下備選方案:

  1. 使用Open Session In View模式在每個請求上創建會話,並在返回響應之前提交事務。

  2. 實現DTO(數據傳輸對象)層,以便我執行的每個DAO查詢都返回正確初始化的DTO以用於我的目的。 我真的不太喜歡這個選項,因為根據我的經驗,我發現它創建了許多樣板復制代碼並且變得很難維護。

  3. 不要映射JPA中的任何關聯,以便我執行的每個查詢只返回我感興趣的實體 - 這可能要求我無論如何都要有DTO並且維護很難,我認為這樣做會破壞ORM的目的首先。

  4. 急切地獲取所有(或大多數關聯) - 在上面的示例中,總是在檢索訂單時獲取所有訂單行。

所以我的問題是,你何時以及在什么情況下會使用哪些選項? 你總是堅持一種做法嗎?

我會問一位同事,但我認為,如果我甚至提到“開放式會議”這一術語,我會受到空白的盯着:(我真正想要的是來自資深或非常有經驗的開發人員的一些建議。

多謝你們!

Open View in View存在一些問題

例如, 如果事務失敗,您可能在提交時知道得太晚 ,一旦您幾乎完成渲染頁面(可能已經提交了響應,因此您無法更改頁面!)...如果您已經知道之前的那個錯誤,你會遵循不同的流程並最終呈現一個不同的頁面......

其他例子,按需讀取數據可能會轉向許多“N + 1選擇”問題 ,這會影響您的性能。


許多項目使用以下路徑:

  1. 維護業務層的交易 ; 在那一點加載你應該需要的一切。
  2. 表示層冒着LazyExceptions的風險:每個都被認為是編程錯誤,在測試期間被捕獲,並通過在業務層中加載更多數據來糾正(您有機會有效地執行此操作,避免“N + 1選擇”問題)。

為避免為DTO創建額外的類,您可以在實體對象本身內加載數據 這是POJO方法的全部要點(現代數據訪問層使用,甚至像Spring這樣的集成技術)。

我已經成功解決了Open Session In View -pattern(即Spring實現)的所有延遲初始化問題。 我使用的技術與您完全相同。

使用此模式允許我完全映射實體關系,而不用擔心在dao中獲取子實體。 大多。 在90%的情況下,模式解決了視圖中的延遲初始化需求。 在某些情況下,您必須“手動”初始化關系。 這些案例很少見,在我的案例中總是涉及非常復雜的映射。

在視圖模式中使用Open Entity Manager時,正確定義實體關系,尤其是傳播和事務設置非常重要。 如果這些配置不正確,當某個實體在視圖中被懶惰地初始化並且由於會話已經關閉而失敗時,將會出現與已關閉會話相關的錯誤。

我肯定會選擇選項1.有時可能需要選項2,但我認為絕對沒有理由使用選項3.選項4也是不可以。 急切地獲取所有內容會導致任何需要列出某些父實體的一些屬性的視圖的性能(在這種情況下為訂單)。

N + 1選擇

在開發期間,由於初始化視圖中的某些關系,將會有N + 1個選擇。 但這並不是放棄這種模式的理由。 只需解決這些問題,並在將代碼交付到生產環境之前。 使用OEMIV模式解決這些問題就像使用任何其他模式一樣容易:添加正確的dao或服務方法,修復控制器以調用不同的finder方法,可能會向數據庫添加視圖等。

我已成功在項目中使用Open-Session-in-View模式。 但是,如果您在較低層管理事務同時在視圖層中保持Hibernate會話打開,我最近在“Spring In Practice”中讀到了一個非可重復讀取的有趣潛在問題。

我們管理了服務層中的大部分事務,但是在視圖層中保持了hibernate會話的開放性。 這意味着視圖中的延遲讀取導致單獨的讀取事務。

我們在服務層管理交易以最小化交易持續時間。 例如,我們的一些服務調用導致數據庫事務和對外部服務的Web服務調用。 我們不希望在等待Web服務調用響應時打開我們的事務。

由於我們的系統從未投入生產,我不確定它是否存在任何實際問題,但我懷疑該視圖有可能試圖延遲加載已被其他人刪除的對象。

但是,DTO方法有一些好處。 您必須事先考慮您需要哪些信息。 在某些情況下,這將阻止您生成n + 1個選擇語句。 它還有助於查看在哪里使用預先獲取和/或優化的視圖。

我也將重點放在Open-Session-in-View模式之后,之前曾經在同一條船上。

我在沒有彈簧的情況下使用Stripes,並且在使用之前創建了一個手動過濾器。 正如你所提到的,后端的編碼事務邏輯變得很亂。 當您將越來越多的對象映射到彼此時,急切地抓取所有內容變得可怕。

我想補充一點,你可能沒有遇到的是Stripersist和Stripernate - Stripersist更具JPA味道 - 自動保濕過濾器可以讓你的大量工作脫穎而出。

使用Stripersist,您可以說/appContextRoot/actions/view/3 ,它會在執行事件之前自動保存ActionBean上的JPA實體,其id為3。

Stripersist是sourceforge上的 stripe -stuff包 我現在將它用於所有新項目,因為它很干凈,並且在必要時可以輕松支持多個數據源。

訂單和訂單行是否構成大量數據? 他們是否參與需要實時響應的在線流程? 如果是這樣,你可能會考慮不使用渴望的提取 - 它確實在性能方面產生了很大的差異。 如果數據量很小,則急切提取沒有問題。

關於使用DTO,它可能是一個可行的實現。 如果您的業務層由您自己的應用程序在內部使用(即一個小型Web應用程序及其業務邏輯),那么最好在視圖中使用您自己的實體在視圖模式中使用開放會話,因為它更簡單。

如果您的實體被許多應用程序(即在您的公司中提供服務的后端應用程序)使用,那么使用DTO會很有趣,因為您不會將模型暴露給您的客戶。 揭露它可能意味着你將很難重構你的模型,因為它可能意味着與你的客戶違約。 由於您有另一層抽象,DTO會使這更容易。 這可能有點奇怪,因為EJB3理論上不需要DTO。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM