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