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