Struts+Spring+Hibernate整合笔记一
OpenSessionInview:
1.如果当前方法没有事物环境,则调用完毕getHibernate以后。session关闭;
说明:1如果测试dao层,没有事物环境
2如果测试service层,但是如果service层的方法没有包含在事物的声明中,则也没有事物环境
2.如果当前方法有事物环境,则不能关闭session
3.如果事物环境方法被调用完毕以后,session关闭
背景:
hibernate 允许对关联对象、属性进行延迟加载,但是必须保证延迟加载的操作限于同一个 Hibernate Session 范围之内进行。如果 Service 层返回一个启用了延迟加载功能的领域对象给 Web 层,当 Web 层访问到那些需要延迟加载的数据时,由于加载领域对象的 Hibernate Session 已经关闭,这些导致延迟加载数据的访问异常。
把一个Hibernate Session和一次完整的请求过程对应的线程相绑定。目的是为了实现”Open Session in View”的模式。例如: 它允许在事务提交之后延迟加载显示所需要的对象。
OpenSessionInViewFilter 过滤器将 Hibernate Session 绑定到请求线程中,它将自动被 spring 的事务管理器探测到。所以 OpenSessionInViewFilter 适用于 Service 层使用HibernateTransactionManager 或 JtaTransactionManager 进行事务管理的环境,也可以用于非事务只读的数据操作中。
在不同的技术框架下,实现Open session in view的手段不同:
在servlet中用过滤器实现
在struts中用拦截器实现
在spring中使用AOP实现
这里给出在ssh框架中用spring的AOP实现:
配置:
<filter>
<filter-name>Spring OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param> <!--
指定org.springframework.orm.hibernate3.LocalSessionFactoryBean在spring配置文件中的名称,默认值为sessionFactory
如果LocalSessionFactoryBean在spring中的名称不是sessionFactory,该参数一定要指定,否则会出现找不到sessionFactory的异常
-->
<param-name>sessionFactoryBean</param-name>
<param-value>sessionFactory</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Spring OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
原理:
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;
if (isSingleSession()) {
// single session mode
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
// Do not modify the Session: just set the participate flag.
participate = true;
}
else {
logger.debug("Opening single Hibernate Session in OpenSessionInViewFilter");
Session session = getSession(sessionFactory);
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
}
else {
// deferred close mode
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
// Do not modify deferred close: just set the participate flag.
participate = true;
}
else {
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}
try {
filterChain.doFilter(request, response);
}
finally {
if (!participate) {
if (isSingleSession()) {
// single session mode
SessionHolder sessionHolder =
(SessionHolder) TransactionSynchronizationManager.unbindResource(sessionFactory);
logger.debug("Closing single Hibernate Session in OpenSessionInViewFilter");
closeSession(sessionHolder.getSession(), sessionFactory);
}
else {
// deferred close mode
SessionFactoryUtils.processDeferredClose(sessionFactory);
}
}
}
} protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
/**
* 从spring的上下文中取得SessionFactory对象
* WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
* return (SessionFactory) wac.getBean(getSessionFactoryBeanName(),SessionFactory.class);
* getSessionFactoryBeanName()方法默认返回"sessionFactory"字符串,在spring配置文件中可要注意了,别写错了.
*/
SessionFactory sessionFactory = lookupSessionFactory(request);
boolean participate = false;// 标识过滤器结束时是否进行关闭session等后续处理
if (isSingleSession()) {//单session模式
//判断能否在当前线程中取得sessionFactory对象对应的session
if (TransactionSynchronizationManager.hasResource(sessionFactory)) {
//当能够找到session的时候证明会有相关类处理session的收尾工作,这个过滤器不能进行关闭session操作,否则会出现重复关闭的情况.
participate = true;//但我并没有想出正常使用的情况下什么时候会出现这种情况.
} else {
Session session = getSession(sessionFactory);//当前线程取不到session的时候通过sessionFactory创建,下面还会详细介绍此方法
//将session绑定到当前的线程中,SessionHolder是session的一层封装,里面有个存放session的map,而且是线程同步的Collections.synchronizedMap(new HashMap(1));
//但是单session模式下一个SessionHolder对应一个session,核心方法是getValidatedSession 取得一个open状态下的session,并且取出后从map中移出.
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(session));
}
} else {//这段是非单session模式的处理情况,没有研究.但粗略看上去,大概思想是一样的
if (SessionFactoryUtils.isDeferredCloseActive(sessionFactory)) {
participate = true;
} else {
SessionFactoryUtils.initDeferredClose(sessionFactory);
}
}
try {
//将session绑定到了当前线程后,就该处理请求了
filterChain.doFilter(request, response);
}finally {
if (!participate) {
if (isSingleSession()) {
//当请求结束时,对于单session模式,这时候要取消session的绑定,因为web容器(Tomcat等)的线程是采用线程池机制的,线程使用过后并不会销毁.
SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
.unbindResource(sessionFactory);
//取消绑定只是取消session对象和线程对象之间的引用,还没有关闭session,不关闭session相对于不关闭数据库连接,所以这里要关闭session
closeSession(sessionHolder.getSession(), sessionFactory);
} else {
//非单session模式,没有研究.
SessionFactoryUtils.processDeferredClose(sessionFactory);
}
}
}
步骤:
1. 获取session,打开session
2. filterChain.doFilter(request, response);
3. 关闭session
在2中可能执行了若干的Servlet、JSP、Action等等,最终处理完渲染完页面之后,再进入OpenSessionInViewFilter的3关闭session
现在只要保证在2中不论是Servlet、JSP还是Action中执行DAO时获取的session都是1中打开的同一个session,并且在DAO关闭session时并不实际关闭,留到OpenSessionInViewFilter的3中再最终关闭,就实现了懒加载了,因为只要是在OpenSessionInViewFilter过滤的范围内,session都处于打开,比如在一个Servlet中查到一个Bean,这时他的关联实体并没有加载,当这个Servlet重定向到一个JSP,在其中得到这个Bean后直接访问之前没加载的那些关联实体,会实时的加载这个关联实体,因为session还未关闭,这便是懒加载了。
解决方法:使用spring提供的过滤器
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>day04-02-itheima08-s2sh</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/applicationContext.xml</param-value>
</context-param> <filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping> <filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
web.xml
Struts+Spring+Hibernate整合笔记一的更多相关文章
- Struts+Spring+Hibernate整合入门详解
Java 5.0 Struts 2.0.9 Spring 2.0.6 Hibernate 3.2.4 作者: Liu Liu 转载请注明出处 基本概念和典型实用例子. 一.基本概念 St ...
- Struts+Spring+Hibernate整合
这段笔记三两年前写的,一直因为一些琐事,或者搞忘记了,没有发.今天偶然翻出了它,就和大家一起分享下吧. 1.导入jar包 Struts的jar包: Spring的jar包: Hibernate的jar ...
- Struts+Spring+Hibernate、MVC、HTML、JSP
javaWeb应用 JavaWeb使用的技术,比如SSH(Struts.Spring.Hibernate).MVC.HTML.JSP等等技术,利用这些技术开发的Web应用在政府项目中非常受欢迎. 先说 ...
- 笔记58 Spring+Hibernate整合(一)
Spring+Hibernate整合 一.整合思路 使DAO继承HibernateTemplate这个类 HibernateTemplate这个类提供了setSessionFactory()方法用于注 ...
- 用eclipse搭建SSH(struts+spring+hibernate)框架
声明: 本文是个人对ssh框架的学习.理解而编辑出来的,可能有不足之处,请大家谅解,但希望能帮助到大家,一起探讨,一起学习! Struts + Spring + Hibernate三者各自的特点都是什 ...
- Struts2+Spring+Hibernate整合开发(Maven多模块搭建)
Struts2+Spring+Hibernate整合开发(Maven多模块搭建) 0.项目结构 Struts2:web层 Spring:对象的容器 Hibernate:数据库持久化操作 1.父模块导入 ...
- SSH(struts+spring+hibernate)常用配置整理
SSH(struts+spring+hibernate)常用配置整理 web.xml配置 <?xml version="1.0" encoding="UTF-8&q ...
- MyEclipse下Spring+Hibernate整合
目前,SSH(Struts+Spring+Hibernate)是Web开发的一种常用框架组合,Struts实现了MVC,Hibernate实现了关系对象映射,Spring实现了基于Bean的配置管理. ...
- Struts+Spring+Hibernate项目的启动线程
在Java Web项目中,经常要在项目开始运行时启动一个线程,每隔一定的时间就运行一定的代码,比如扫描数据库的变化等等.要实现这个功能,可以现在web.xml文件中定义一个Listener,然后在这个 ...
随机推荐
- html标签的快捷
https://www.jianshu.com/p/8f330e3571ee 一: <ul> <li><a href=""></a> ...
- 关于mybatis中sql映射文件模糊查询的使用
1.从前台传递一个String类型的参数到后台进行查询,如果牵涉到模糊查询会报错,应该把参数封装到对象中再进行传递然后进行模糊查询 2.一个查询框,多个查询条件 <if test="c ...
- IDE - IDEA - 代码缩进设置
1. 概述 Idea 的代码缩进设置 2. 场景 最近进场会从别的地方找到代码, 然后导入 Idea 时长出现 缩进的问题 会 弹出 以下提示 # 后面还有 3 个 可选按钮 this file in ...
- cpu io disk mem监控 python
import psutil def cpu_information(): #scputimes(user=26.9, nice=0.1, system=50.27, idle=8551.89, iow ...
- Multisim中'地'的问题
1.地其实就是一个参考电压 对于示波器而言,只用连接一个探头,另一个探头默认就是连接地.
- RedHat7.0 网络源的配置
RedHat7.0 yum源的配置 写这篇随笔的目的 为了记录自己的操作,能够为以后的再次配置提供参考 因为网上的教程都有些年代了,为了方便其他同学方便配置 提高下自己的写作水平 参考资料 RedHa ...
- TensorFlow 模型的保存与载入
参考学习博客: # https://www.cnblogs.com/felixwang2/p/9190692.html 一.模型保存 # https://www.cnblogs.com/felixwa ...
- VMware安装EVE
众所周知,EVE是一个非常强大的仿真环境,能给我们学习带来很大的帮助,这里主要简单记录一下安装在VMware下安装EVE的过程. 1.准备: 我安装的VMware是WORKSTATION 12 PRO ...
- 【C语言】创建一个函数,判断某一正整数是否为水仙花数,并调用这个函数找出1000以内所有水仙花数
#include <stdio.h> int fun(int x) { int a, b, c; a = x / ; b = x % / ; c = x % ; if (x == a * ...
- LeetCode练题——35. Search Insert Position
1.题目 35. Search Insert Position Easy 1781214Add to ListShare Given a sorted array and a target value ...