公司下午比较清闲,和同事谈spring如何管理session的事(同事已有三年的j2ee开发经验),起初,我对spring管理session概念很是模糊,不知道spring什么时候从sessionFactory取出session.最初我以为在dao层spring会产生session,但是越想越不能自圆其说,使我产生这种想法的是在我初学hibernate后,可在dao层得到session,而且dao是data access object(数据访问对象),理所应当应该在dao层管理session,但是公司的项目是用spring来管理hibernate的,经过一番请教,同事告诉我由于事务配置在service层,所以当客户端发过来一个请求,spring会在service层管理session和transaction,由于事务的acid特性,所以共用同一个session的service才可以正常回滚,总之,还是有些模糊,所以上网收集了一些资料,分享给和我一样对spring管理session模糊的朋友。
txObject.getSessionHolder().setSynchronizedWithTransaction(true); session=txObject.getSessionHolder().getSession(); Connectioncon=session.connection(); IntegerpreviousIsolationLevel=DataSourceUtils.prepareConnectionForTransaction(con,definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); if(definition.isReadOnly()&&txObject.isNewSessionHolder()){ //JustsettoNEVERincaseofanewSessionforthistransaction. session.setFlushMode(FlushMode.NEVER); }//如果是只读事务,并且sessionholder是新建的,那么就设置hibernate的flushmode为never if(!definition.isReadOnly()&&!txObject.isNewSessionHolder()){ //WeneedAUTOorCOMMITforanon-read-onlytransaction. FlushModeflushMode=session.getFlushMode(); if(FlushMode.NEVER.equals(flushMode)){ session.setFlushMode(FlushMode.AUTO); //如果session的flushmode是nerver,就设置为auto,因为如果事务定义成非readonly,那么这个session一定是可以flush的 txObject.getSessionHolder().setPreviousFlushMode(flushMode); } } //AddtheHibernatetransactiontothesessionholder. txObject.getSessionHolder().setTransaction(session.beginTransaction());//开始一个事务,并把这个事务对象放到sessionholder中,随后这个sessionholder会通过threadlocal放到线程中,以供在commit时使用 //Registertransactiontimeout. if(definition.getTimeout()!=TransactionDefinition.TIMEOUT_DEFAULT){ txObject.getSessionHolder().setTimeoutInSeconds(definition.getTimeout());//设置超时时间,如果其超时时间为-1,则不进行设置,如果不是-1,那么超时时间是这样设置的newDate(System.currentTimeMillis()+millis*1000);既程序员在配置文件中指定的其实是秒数 } //RegistertheHibernateSession'sJDBCConnectionfortheDataSource,ifset. if(getDataSource()!=null){ ConnectionHolderconHolder=newConnectionHolder(con); if(definition.getTimeout()!=TransactionDefinition.TIMEOUT_DEFAULT){ conHolder.setTimeoutInSeconds(definition.getTimeout()); } if(logger.isDebugEnabled()){ logger.debug("ExposingHibernatetransactionasJDBCtransaction["+con+"]"); } TransactionSynchronizationManager.bindResource(getDataSource(),conHolder); txObject.setConnectionHolder(conHolder); } //Bindthesessionholdertothethread. if(txObject.isNewSessionHolder()){ TransactionSynchronizationManager.bindResource(getSessionFactory(),txObject.getSessionHolder());//如果是新的sessionholder则绑定到线程。这样在进入方法栈中的下一个方法时就能得到整个sessionholder了,connectionholder亦是如此 } } catch(Exceptionex){ SessionFactoryUtils.releaseSession(session,getSessionFactory());//如果抛出异常就释放这个session,这个操作还会在后面出现 thrownewCannotCreateTransactionException("CouldnotopenHibernateSessionfortransaction",ex); } }
通过以上对代码的注释可以知道,如果给service设置声明式事务管理,假设事务传播途径为required,然后一个service调用另一个service时,他们其实是共用一个session,原则是没有就创建,有就不创建,并返回之前已创建的session和transaction。也就是说spring通过threadlocal把session和对应的transaction放到线程之中,保证了在整个方法栈的任何一个地方都能得到同一个session和transaction。
所以如果你的方法在事务体之内,那么你只要通过hibernatesupportdao或者hibernatetemplate来得到session的话,那这个session一定是开始事务的那个session,这个得到session的主要方法在SessionFactoryUtils里,我们来看一下
(这里还有一个小细节,public abstract class SessionFactoryUtils ,Juergen Hoeller在写工具类的时候为了不能让其有实例使用的是abstract,而我们一般的做法是final类加private的构造方法,看上去不怎么雅观,看看源代码还是能学习到不少写代码的技巧的)
在SessionFactoryUtils的doGetSession里写到,如果当前线程有绑定session,则返回这个session,如果没有绑定session,则看是否允许创建(既allowCreate这个参数是true还是false,这个参数将会在很多地方设计到,比如说hibernatetemplate和hibernatedaosupport里都有),如果不允许创建就抛出一个原始的hibernateException,举个例子,如果你没有给某个service方法配置声明式事务管理,而却要在这个service所调用的dao里得到当前得session,这样就会报这个错了:
if(method.getName().equals("getCurrentSession")){ //HandlegetCurrentSessionmethod:returntransactionalSession,ifany. try{ returnSessionFactoryUtils.doGetSession((SessionFactory)proxy,false); //最后一个参数是false,说明这个方法不能返回一个新的session,没有就抛异常 } catch(IllegalStateExceptionex){ thrownewHibernateException(ex.getMessage()); } }
相关推荐
Spring Session 是一个开源项目,由 Pivotal Software 开发,旨在提供一种在分布式环境中管理用户会话(Session)的方式。这个例子工程展示了如何在实际应用中集成 Spring Session 来实现跨服务器的会话共享,这对于...
本文将深入探讨SpringSession如何支持Cookie和header策略,并解析`CookieHeaderHttpSessionStrategy.java`这个文件中的关键概念和技术细节。 首先,我们来看标题提及的“SpringSession同时支持Cookie和header策略”...
《Spring Session 深度解析:1.3.1.RELEASE 版本详解》 Spring Session 是一个开源项目,由 Pivotal Software 开发并维护,它为 Spring 应用程序提供了一种集中管理会话数据的方式,尤其适用于分布式环境。在 1.3.1...
《Spring Session深度解析与实战指南》 在现代的Web应用开发中,会话管理是至关重要的部分,Spring Session作为Spring框架的一部分,为开发者提供了一种跨服务器共享HTTP session的解决方案。本文将深入探讨Spring ...
### Spring源码解析知识点 #### 一、Spring IoC 容器详解 ##### 1. BeanFactory —— 最基础的IoC容器 - **概念**:`BeanFactory` 是Spring框架中最基本的IoC容器,它负责管理Bean的生命周期,包括创建、配置和...
分布式session简介和 spring session 源码 解析 适合想了解分布式 session的基础知识,想从源码层面了解spring session的同学
6. **Spring与Hibernate集成**:"spring源代码解析(八):spring驱动Hibernate的实现.doc"探讨了Spring如何与ORM框架Hibernate协同工作,包括SessionFactory的创建、Session管理以及事务策略的配置。 7. **Spring ...
本篇文章将详细解析Spring Security 3.x中的会话管理和相关知识点。 1. **会话管理基础** - 会话在Web应用中扮演着关键角色,它允许服务器存储和跟踪用户的状态。在Spring Security中,会话管理主要涉及到会话固定...
【SpringSession架构与设计】 在Web开发中,Session管理和用户状态保持是一个关键问题。传统的Cookie和LocalStorage虽然可以存储用户信息,但它们都有局限性。比如,Cookie可能存在安全风险,LocalStorage不能跨域...
"Spring session实现共享单点登录案例过程解析" 本文主要介绍了Spring session实现共享单点登录案例过程解析,通过示例代码详细介绍了Spring session实现共享单点登录的过程。 一、项目构建 要实现共享单点登录,...
在创建`SessionFactory`的过程中,Spring还会对`SessionFactory`进行包装,通过`wrapSessionFactoryIfNecessary()`方法插入对`getCurrentSession`的拦截,目的是为了获取与当前事务关联的`Session`。这样可以确保在...
Spring Session 整合 Redis 过程解析 Spring Session 简介 在传统的单机 Web 应用中,用户的会话 Session 都是由容器管理的。浏览器使用 Cookie 中记录 SessionId,容器根据 SessionId 判断用户是否存在会话 ...
Spring Session是一个基于Spring Boot的Session管理框架,它提供了一种简单的方式来管理Session信息。Spring Session可以将Session信息存储在多种类型的存储介质中,如Redis、Memcached、数据库等。 三、基于Spring...
### Hibernate与Spring集成配置详解 ...通过这些配置,可以实现对数据库的高效访问,并利用Spring的事务管理机制来简化业务逻辑的编写过程。在实际项目开发中,根据具体需求还可以进一步扩展和完善这些配置。
### Spring源码解析知识点 #### 1. Spring IoC 容器概述 Spring 框架的核心特性之一是它的依赖注入(Dependency Injection, DI)能力,这种能力通过一个称为 Inversion of Control (IoC) 容器来实现。IoC 容器负责...
在实际开发中,有些框架如Spring已经内置了对ThreadLocal的管理和清理机制,可以更方便地在多线程环境中使用session。 总结,ThreadLocal是Java中处理线程局部数据的利器,特别适用于需要线程隔离的场景,如Web...
2. **spring-aop-2.0.6.jar**:AOP(Aspect Oriented Programming,面向切面编程)是Spring的重要特性,允许开发者定义“切面”,即关注点的模块化,如日志、事务管理等。此jar包提供了动态代理机制,实现了方法拦截...
这个基于Spring MVC的简易用户管理案例为初学者提供了一个很好的学习平台,让我们一起深入探讨其中的关键知识点。 首先,Spring MVC是Spring框架的一个模块,主要负责处理HTTP请求并返回响应。它采用了模型-视图-...