OpenSessionInView模式總結
OpenSessionInView模式的起源:
OpenSessionInViewFilter是Spring提供的一個針對Hibernate的一個支援類,其主要意思是在發起一個頁面請求時開啟Hibernate的Session,一直保持這個Session,直到這個請求結束,具體是通過一個Filter來實現的。
由於Hibernate引入了Lazy Load特性,使得脫離Hibernate的Session週期的物件如果再想通過getter方法取到其關聯物件的值,Hibernate會丟擲一個 LazyLoad的Exception。所以為了解決這個問題,Spring引入了這個Filter,使得Hibernate的Session的生命週期變長。
一個簡單的例子。
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain filterChain) throws IOException, ServletException {
- try{
- Session session=HibernateSessionFactoryUtils.getSession();
- request.setAttribute(HIBERNATE_SESSIN_KEY, session);
- log.debug("客戶端請求開始,Hibernate Session已開啟.........");
- filterChain.doFilter(request, response);
- }finally {
- Object obj=request.getAttribute(HIBERNATE_SESSIN_KEY);
- if(obj!=null&&obj instanceof Session){
- Session session=(Session)obj;
- session.close();
- log.debug("客戶端請求結束,Hibernate Session已關閉.........");
- }else{
- log.error("客戶端請求結束,Hibernate Session未發現,請檢查程式碼....");
- }
- }
- }
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
try{
Session session=HibernateSessionFactoryUtils.getSession();
request.setAttribute(HIBERNATE_SESSIN_KEY, session);
log.debug("客戶端請求開始,Hibernate Session已開啟.........");
filterChain.doFilter(request, response);
}finally {
Object obj=request.getAttribute(HIBERNATE_SESSIN_KEY);
if(obj!=null&&obj instanceof Session){
Session session=(Session)obj;
session.close();
log.debug("客戶端請求結束,Hibernate Session已關閉.........");
}else{
log.error("客戶端請求結束,Hibernate Session未發現,請檢查程式碼....");
}
}
}
缺點:使用了OpenSessionInView 模式後造成了記憶體和資料庫連線問題
由於使用了OpenSessionInView 模式,Session的生命週期變得非常長。雖然解決了Lazy Load的問題,但是帶來的問題就是Hibernate的一級快取,也就是Session級別的快取的生命週期會變得非常長,那麼如果你在你的 Service層做大批量的資料操作時,其實這些資料會在快取中保留一份,這是非常耗費記憶體的。還有一個資料庫連線的問題,存在的原因在於由於資料庫的 Connection是和Session綁在一起的,所以,Connection也會得不到及時的釋放。因而當系統出現業務非常繁忙,而計算量又非常大的時候,往往資料連線池的連線數會不夠。這個問題我至今非常頭痛,因為有很多客戶對資料連線池的數量會有限制,不會給你無限制的增加下去。
在本地開發測試的時候沒出現問題,但試想下如果流程中的某一步被阻塞的話,那在這期間connection就一直被佔用而不釋放。最有可能被阻塞的就是在寫Jsp這步,一方面可能是頁面內容大,response.write的時間長,另一方面可能是網速慢,伺服器與使用者間傳輸時間久。當大量這樣的情況出現時,就有連線池連線不足,造成頁面假死現象。
解決方案:
1,使用OpenSessionInView Interceptor來代替這個Filter
2,使用Hibernate.initialize()方法初始會延遲載入的物件
相關文章
- OpenSessionInView是反模式SessionView模式
- opensessioninviewSessionView
- 策略模式總結模式
- 代理模式總結模式
- dao模式總結模式
- 設計模式總結(模式篇)設計模式
- 單例模式總結單例模式
- 設計模式總結設計模式
- JavaScript設計模式總結JavaScript設計模式
- PHP設計模式總結PHP設計模式
- 前端設計模式總結前端設計模式
- 觀察者模式的總結模式
- 【設計模式總結篇】設計模式
- 設計模式大總結(六):命令模式設計模式
- php設計模式總結-單件模式PHP設計模式
- php設計模式總結-工廠模式PHP設計模式
- 設計模式總結 —— 單例設計模式設計模式單例
- React 元件模式學習總結React元件模式
- C++設計模式 - 總結C++設計模式
- 設計模式總結篇系列:建造者模式(Builder)設計模式UI
- 紅寶書總結-原型模式原型模式
- Java設計模式簡介(總結)Java設計模式
- 保護模式篇——總結與提升模式
- 設計模式總結(理論篇)設計模式
- OpenSessionInView裡的Session不能自動關閉?SessionView
- 用到的設計模式總結--單例模式+工廠方法模式+Builder模式設計模式單例UI
- 總結 - 設計模式,企業應用架構模式,架構模式設計模式應用架構
- PHP設計模式學習最全總結PHP設計模式
- 設計模式簡單總結(待完善)設計模式
- 一文總結設計模式設計模式
- 設計模式總結(實踐篇1)設計模式
- C#設計模式之總結篇C#設計模式
- Java中單例設計模式總結Java單例設計模式
- 推薦:通用設計模式的總結設計模式
- 建立型設計模式對比總結 設計模式(八)設計模式
- 設計模式總結——代理模式以及java的動態代理設計模式Java
- Java設計模式(6)之觀察者模式學習總結Java設計模式
- 設計模式系列——3.簡單工廠模式與策略模式總結設計模式