2017-03-10

Open Session in View

突然想起以前設定過 Struts2 中某個 filter,順手把之前的筆記再重新整理釐清。

Entity Manager and Transaction Manager
  • 簡單來說,entity manager 關係到資料讀取,而 transaction manager 關係到資料寫入。
  • 但兩者並非完全脫鉤,例如:在一個 transaction 中可能要參照其他 entity 的資料,或讀取 entity 時要避免 dirty data。
  • 因此 entity 要負責追蹤資料的狀態 (entity state),提供 transaction 中使用。

Open Session in View (OSIV)
  • Open Session in View 中的 session 指的是 Hibernate session
  • 用意在於避免 view rendering 的過程中,Hibernate session 過早結束導致後續 data lazy loading 產生 LazyInitializationExceptions
  • 換言之,Open Session in View 拉長 Hibernate session 的時間,並交由 view request 控制。
  • 值得注意的是:Hibernate session 結束與否不同等於 transaction commit or rollback;在純粹讀取資料的應用,操作是不需要 transaction 保護的,若是讀寫混合,Hibernate session 關閉的時機涉及 transaction 如何向 session factory 取得 Hibernate session,getCurrentSession() or openSession(),前者由 SessionFactory 自動控制,後者才需要手動在 commit or rollback 後關閉。

主張 OSIV 為 anti-pattern 的觀點集中於:
  • OSIV 忽略 readonly 與 read-write 操作本質上的不同,不應該都由 entity 決定一次存取的資料量。
  • 直接拉長 Hibernate session 給予底層實作傾向 lazy fetch 的空間,嚴重將導致 (n+1) select issue。
  • 精細一些的作法,應該由 view 決定底層應該一次 fetch 哪些欄位的資料,使用 DTO projection,而非單純由 entity 決定一次取回的欄位數量。
  • 但此種作法將提高 view 與底層 DTO 的耦合;傳統 view 只依賴 domain model,DTO 與 view 之間互不依賴。
  • 注意:這邊指的一次存取資料量,與分頁查詢無關,分頁查詢的 query 會帶有 order 與起始/結束的 row number。
Hibernate Session and Entity Manager
  • Entity Manager 是 JPA 定義的名詞,而 Hibernate session 及 SessionFactory 則是 Hibernate 特有。
  • 一般起始的順序是:transaction manger, entity manager, Hibernate session,透過 entity manager 控制 session,避免手動控制。
see also:

沒有留言: