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
<
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);
}