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 中embed标签使用
代码如下: embed src=url 说明:embed可以用来插入各种多媒体,格式可以是 Midi.Wav.AIFF.AU.MP3.PDF.jpg等等,Netscape及新版的IE 都支持.url为 ...
- python字典里面列表排序
#coding=utf8 #获取到的数据库ip,和负载数据,需要按照负载情况排序 a={u'1.8.1.14': [379, 368, 361, 358, 1363], u'9.2.4.3': [42 ...
- Codeforces Round #618 (Div. 1)A(观察规律)
实际上函数值为x&(-y) 答案仅和第一个数字放谁有关 #define HAVE_STRUCT_TIMESPEC #include <bits/stdc++.h> using na ...
- 网站复制工具:HTTrack
HTTrack简介: HTTrack是Kali中内置的工具,主要用于克隆网站.渗透测试人员可以利用它来在自主可控制的环境中查看该网站的完整内容:所有离线文件.同时可以利用该网站的副本来开发假冒的钓鱼网 ...
- ioutils
import yaml import json import csv import configparser class IoUtils(object): """ dep ...
- PTA喊山
喊山 喊山,是人双手围在嘴边成喇叭状,对着远方高山发出“喂—喂喂—喂喂喂……”的呼唤.呼唤声通过空气的传递,回荡于深谷之间,传送到人们耳中,发出约定俗成的“讯号”,达到声讯传递交流的目的.原来它是彝族 ...
- Color the ball(差分数组)
N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气球a开始到气球b依次给每个气球涂一次颜色.但 ...
- MySQL主从复制(一主两从)
主库开启bin-log二进制日志功能,并建立slave账号,并授权从库连接主库,从库通过change master得到主库的相关同步信息, 然后连接主库进行验证,主库产生的新数据会导入到bin- ...
- centos 6.5 防火墙通过 80 和 3306 端口
vim /etc/sysconfig/iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 22 -j ACCEPT -A INPU ...
- Python 爬取 热词并进行分类数据分析-[App制作]
日期:2020.02.14 博客期:154 星期五 [本博客的代码如若要使用,请在下方评论区留言,之后再用(就是跟我说一声)] 所有相关跳转: a.[简单准备] b.[云图制作+数据导入] c.[拓扑 ...