OpenSessionInViewInview是什么?
OpenSessionInViewFilter是Spring提供的一个针对Hibernate的一个支持类其主要意思是在发起一个页面请求时打开Hibernate的Session一直保持这个Session直到这个请求结束具体是通过一个Filter来实现的
当然在我的理解OpenSessionInView是Hibernate的一种模式因为官方也给出了相关代码
JBoss的OpenSessionInView的地址
OpenSessionInView简单来说就是在请求到达View时Session不关闭可以方便的调用Session中的方法由于Hibernate引入了Lazy特性使得脱离Hibernate的Session周期的对象如果再想通过getter方法取到其关联对象的值Hibernate会抛出一个LazyLoad的Exception所以为了解决这个问题Spring和Hibernate都给出了相应的解决方案
Spring的方案是一个过滤器只需要你配置就OK了
但是我目前公司的项目用的是单Hibernate一个框架以前公司未解决懒加载问题将所有的关联对象的lazy全部设为false这样大大降低了系统的运行效率为了解决这个问题自动翻阅资料找到了Hibernate官方的OpenSessionInView模式此模式是一个Filter
package monhibernate;import javaioIOException;import javaxservletFilter;import javaxservletFilterChain;import javaxservletFilterConfig;import javaxservletServletException;import javaxservletServletRequest;import javaxservletServletResponse;import orghibernateSessionFactory;import orghibernateStaleObjectStateException;/* * Hibernate的OpenSessionInView过滤器可以实现在页面中Session依旧不关闭解决懒加载带来的副作用可以随意使用懒加载提升系统效率 * * @author wurt * */public class HibernateSessionRequestFilter implements Filter {
private SessionFactory sf;
public void doFilter(ServletRequest request
ServletResponse response
FilterChain chain)
throws IOException ServletException {
try {
//开启Session和Transcation在Hibernate查询中需要用getCurrentSession获取当前Session
sfgetCurrentSession()beginTransaction()
// 放行
chaindoFilter(request response)
// Session提交getCurrentSession获取的Session会在提交之后自动关闭
sfgetCurrentSession()getTransaction()commit()
} catch (StaleObjectStateException staleEx) {
throw staleEx;
} catch (Throwable ex) {
// Rollback only
exprintStackTrace()
try {
//如果Transcation依旧存在回滚
if (sfgetCurrentSession()getTransaction()isActive()) {
sfgetCurrentSession()getTransaction()rollback()
}
} catch (Throwable rbEx) {
rbExprintStackTrace()
}
// Let others handle it… maybe another interceptor for exceptions?
throw new ServletException(ex)
}
}
public void init(FilterConfig filterConfig) throws ServletException {
// sessionFactory 可以通过自己的代码获取此值
sf = HibernateSimpleDaosessionFactory;
}
public void destroy() {} }
将此过滤器配置到webxml一切问题都解决了
配制方法如下
<filter>
<filtername>HibernateSessionInView</filtername>
<filterclass>monhibernateHibernateSessionRequestFilter</filterclass></filter><filtermapping>
<filtername>HibernateSessionInView</filtername>
<urlpattern>/*</urlpattern></filtermapping>
然后将公司中Hibernate配置文件的lazy全部去掉一切OK
之前lazy=fasle的情况下载入Hibernate需要查询+甚至更多的SQL然而采用OpenSessionInView仅仅需要条(门户网站首页)
为什么会有这么大的提升?
之前的SQL是不管用不用只要是false全部查出来再说
现在的lazy都是true在初次查询时只会查询实体需要的字段而不会查询关联的对象当在View中需要关联时才会去查询数据库
lazy=true + OpenSessionInView可以避免很多不是必要的查询速度自然会有所提升
使用注意事项
在Dao中无需再创建Transcation因为过滤器已经创建好
使用Session请使用getCurrentSession来获取得到当前的Session而不是openSession新建一个Session
通过getCurrentSession获得的Session无需关闭因为在过滤器提交时会自动关闭
示例代码仅仅贴出一个方法
public List<T> getAll(Class T)
{
Session session = getCurrentSession()
List<T> list = null;
try{
list = sessioncreateQuery(from + TgetName())list()
return list;
}catch (RuntimeException e){
throw e;
} }