原文出自: http://www.aygfsteel.com/waterye/archive/2005/08/23/10836.aspx
OpenSessionInView模式
Spring+Hibernate中,? 集合映射如果使用lazy="true", 當PO傳到View層時, 出現未初始化session已關閉的錯誤,只能在dao先初始化
parent.getChilds().size();
Spring提供Open Session In View來解決這個問題, 有兩種方式
1. Interceptor
??? <!--
?===========?OpenSession?In?View?pattern?==============
-->
???? < bean? id ="openSessionInViewInterceptor"
??????????class ="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" >
???????? < property? name ="sessionFactory" ?ref ="sessionFactory" />
???? </ bean >
???? < bean? id ="urlMapping" ?class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
???????? < property? name ="interceptors" ?ref ="openSessionInViewInterceptor" />
???????? < property? name ="mappings" >
???????????? < props >
??????????? ......
???????????? </ props >
???????? </ property >
???? </ bean >
2. Filter
???? < bean? id ="openSessionInViewInterceptor"
??????????class ="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor" >
???????? < property? name ="sessionFactory" ?ref ="sessionFactory" />
???? </ bean >
???? < bean? id ="urlMapping" ?class ="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping" >
???????? < property? name ="interceptors" ?ref ="openSessionInViewInterceptor" />
???????? < property? name ="mappings" >
???????????? < props >
??????????? ......
???????????? </ props >
???????? </ property >
???? </ bean >
<
web-app
>
?
< filter >
< filter-name > hibernateFilter </ filter-name >
< filter-class >
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</ filter-class >
</ filter >
?
< filter-mapping >
< filter-name > hibernateFilter </ filter-name >
< url-pattern > *.do </ url-pattern >
</ filter-mapping >
</ web-app >
?
< filter >
< filter-name > hibernateFilter </ filter-name >
< filter-class >
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</ filter-class >
</ filter >
?
< filter-mapping >
< filter-name > hibernateFilter </ filter-name >
< url-pattern > *.do </ url-pattern >
</ filter-mapping >
</ web-app >
說明: 個人更喜歡用Interceptor方式, filter是在web.xml中定義
有了OpenSessionInView,并不是一切就ok了。簡單的crud可以,但對于復雜業務邏輯就要想點法子。
OSIV默認是request per session的, 所以即使沒有顯式update(po),Hibernate也會幫你保存的,dao的業務判斷就無效,還好有evict()可用。
update code
// Controller
public ?ModelAndView?update()?{
????p? = ?dao.getVo(id);
????bindObject(request);
????dao.update(p);
}
// Dao
public ?Object?getVo(id)?{
????p? = ?getHibernateTemplate().get(clazz,?id);
????p.getChilds().size();
????getHibernateTemplate().evict(p);
???? return ?p;
}
public ? void ?update(p)?{
????oldP? = ?getVo(id);
???? // ?++--(oldP);
????getHibernateTemplate().update(p);
???? // ?++--(p);
}
public ?ModelAndView?update()?{
????p? = ?dao.getVo(id);
????bindObject(request);
????dao.update(p);
}
// Dao
public ?Object?getVo(id)?{
????p? = ?getHibernateTemplate().get(clazz,?id);
????p.getChilds().size();
????getHibernateTemplate().evict(p);
???? return ?p;
}
public ? void ?update(p)?{
????oldP? = ?getVo(id);
???? // ?++--(oldP);
????getHibernateTemplate().update(p);
???? // ?++--(p);
}