OpenSessionInViewFilter源码分析.docx

上传人:b****8 文档编号:11358161 上传时间:2023-02-28 格式:DOCX 页数:14 大小:21.15KB
下载 相关 举报
OpenSessionInViewFilter源码分析.docx_第1页
第1页 / 共14页
OpenSessionInViewFilter源码分析.docx_第2页
第2页 / 共14页
OpenSessionInViewFilter源码分析.docx_第3页
第3页 / 共14页
OpenSessionInViewFilter源码分析.docx_第4页
第4页 / 共14页
OpenSessionInViewFilter源码分析.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

OpenSessionInViewFilter源码分析.docx

《OpenSessionInViewFilter源码分析.docx》由会员分享,可在线阅读,更多相关《OpenSessionInViewFilter源码分析.docx(14页珍藏版)》请在冰豆网上搜索。

OpenSessionInViewFilter源码分析.docx

OpenSessionInViewFilter源码分析

OpenSessionInViewFilter源码分析

在之前我写的一篇文章

当时我觉得我已经会配置Hibernate的懒加载了,但是,在最近做的课题项目中,相同版本的SSH,一样的配置,却发现懒加载部分成功,我觉得非常的诧异,以为Hibernate映射配置文件*.hbm.xml中设置不对,但是却无功而返。

在网上搜索了许久,还是没有得到想要的答案,最终促使我去读Spring和Hibernate的源码,了解OpenSessionInViewFilter究竟是如何工作的,以及项目中出错的地方为什么session被关闭掉了,什么时候由谁关闭的。

从书上我了解到Session接口是Hibernate向应用程序提供的操纵数据库的最主要接口,它提供了基本的保存、更新、删除和加载Java对象的方法。

Session具有一个缓存,位于缓存中的对象成为持久化对象,它和数据库中的相关记录对应,Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQL语句,来同步更新数据库,这一过程叫清理缓存。

Hibernate把对象分为4种状态:

持久化状态、临时状态、游离状态和删除状态。

临时状态:

刚用new语句创建,还能没有被持久化,并且不处于Session的缓存中。

处于临时状态的Java对象被称为临时对象。

持久化状态:

已经被持久化,并且加入到Session的缓存中。

处于持久化状态的Java对象被称为持久化对象。

删除状态:

不再处于Session的缓存中,并且Session已经计划将其从数据库中删除。

处与删除状态的对象被称为删除对象。

游离状态:

已经被持久化,但不再处于Session的缓存中。

处于游离状态的Java对象被称为游离对象。

在其他文章中找到的图片,很直观。

废话少说,切入正题,在开发SSH项目时,其实并不直接接触到Hibernate的Session,正常的步骤是,先搭建SSH框架,之后设计数据库,再根据数据库逆向工程生成相应的Bean和DAO,接下来根据具体需要将DAO封装成Service供业务逻辑层使用,至始至终都没有显式的创建Session对象,也没有手动关闭它,但是nosessionorsessionclosed却是最常遇到的问题。

其实在逆向工程自动生成的***DAO.java中的每个方法,save();delete();find....其实每次操作都开启和关闭session。

一个自动生成的DAO中的save方法:

[java]viewplaincopy?

publicvoidsave(TenanttransientInstance){log.debug("savingTenantinstance");try{getHibernateTemplate().save(transientInstance);log.debug("savesuccessful");}catch(RuntimeExceptionre){log.error("savefailed",re);throwre;}}

其实内部调用的是HibernateTemplate的save方法,org.springframework.orm.hibernate3.HibernateTemplate的save方法:

[java]viewplaincopy?

publicSerializablesave(finalObjectentity)throwsDataAccessException{return(Serializable)execute(newHibernateCallback(){publicObjectdoInHibernate(Sessionsession)throwsHibernateException{checkWriteOperationAllowed(session);returnsession.save(entity);}},true);}

HibernateTemplate的save方法中调用的execute方法:

[java]viewplaincopy?

publicObjectexecute(HibernateCallbackaction,booleanexposeNativeSession)throwsDataAccessException{Assert.notNull(action,"Callbackobjectmustnotbenull");Sessionsession=getSession();booleanexistingTransaction=SessionFactoryUtils.isSessionTransactional(session,getSessionFactory());if(existingTransaction){logger.debug("Foundthread-boundSessionforHibernateTemplate");}FlushModepreviousFlushMode=null;try{previousFlushMode=applyFlushMode(session,existingTransaction);enableFilters(session);SessionsessionToExpose=(exposeNativeSession?

session:

createSessionProxy(session));Objectresult=action.doInHibernate(sessionToExpose);flushIfNecessary(session,existingTransaction);returnresult;}catch(HibernateExceptionex){throwconvertHibernateAccessException(ex);}catch(SQLExceptionex){throwconvertJdbcAccessException(ex);}catch(RuntimeExceptionex){<mce:

scripttype="text/javascript"src="mce_src="type="text/javascript"src="mce_src="Callbackcodethrewapplicationexception...throwex;}finally{if(existingTransaction){logger.debug("Notclosingpre-boundHibernateSessionafterHibernateTemplate");disableFilters(session);if(previousFlushMode!

=null){session.setFlushMode(previousFlushMode);}}else{//NeverusedeferredcloseforanexplicitlynewSession.if(isAlwaysUseNewSession()){SessionFactoryUtils.closeSession(session);}else{SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session,getSessionFactory());}}}}

可见在execute方法内有获取session和关闭session的语句,绕了这么一大圈才看到session,汗!

[java]viewplaincopy?

protectedSessiongetSession(){if(isAlwaysUseNewSession()){returnSessionFactoryUtils.getNewSession(getSessionFactory(),getEntityInterceptor());}elseif(!

isAllowCreate()){returnSessionFactoryUtils.getSession(getSessionFactory(),false);}else{returnSessionFactoryUtils.getSession(getSessionFactory(),getEntityInterceptor(),getJdbcExceptionTranslator());}}

注意这里获取session和关闭session的方法,非常的重要!

之后在OpenSessionInViewFilter中要提到这里!

这里的session关闭并不是session.close()那么简单,这也是在OpenSessionInViewFilter中打开session后,在这里不会被关闭的原因。

可以看到getSession方法中,是利用SessionFactoryUtils.getNewSession来获取session的,继续深入:

[java]viewplaincopy?

publicstaticSessiongetSession(SessionFactorysessionFactory,booleanallowCreate)throwsDataAccessResourceFailureException,IllegalStateException{try{returndoGetSession(sessionFactory,null,null,allowCreate);}catch(HibernateExceptionex){thrownewDataAccessResourceFailureException("CouldnotopenHibernateSession",ex);}}

[java]viewplaincopy?

privatestaticSessiondoGetSession(SessionFactorysessionFactory,InterceptorentityInterceptor,SQLExceptionTranslatorjdbcExceptionTranslator,booleanallowCreate)throwsHibernateException,IllegalStateException{Assert.notNull(sessionFactory,"NoSessionFactoryspecified");SessionHoldersessionHolder=(SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);if(sessionHolder!

=null&&!

sessionHolder.isEmpty()){//pre-boundHibernateSessionSessionsession=null;if(TransactionSynchronizationManager.isSynchronizationActive()&&sessionHolder.doesNotHoldNonDefaultSession()){//Springtransactionmanagementisactive->//registerpre-boundSessionwithitfortransactionalflushing.session=sessionHolder.getValidatedSession();if(session!

=null&&!

sessionHolder.isSynchronizedWithTransaction()){logger.debug("RegisteringSpringtransactionsynchronizationforexistingHibernateSession");TransactionSynchronizationManager.registerSynchronization(newSpringSessionSynchronization(sessionHolder,sessionFactory,jdbcExceptionTranslator,false));sessionHolder.setSynchronizedWithTransaction(true);//SwitchtoFlushMode.AUTO,aswehavetoassumeathread-boundSession//withFlushMode.NEVER,whichneedstoallowflushingwithinthetransaction.FlushModeflushMode=session.getFlushMode();if(flushMode.lessThan(FlushMode.COMMIT)&&!

TransactionSynchronizationManager.isCurrentTransactionReadOnly()){session.setFlushMode(FlushMode.AUTO);sessionHolder.setPreviousFlushMode(flushMode);}}}else{//NoSpringtransactionmanagementactive->tryJTAtransactionsynchronization.session=getJtaSynchronizedSession(sessionHolder,sessionFactory,jdbcExceptionTranslator);}if(session!

=null){returnsession;}}logger.debug("OpeningHibernateSession");Sessionsession=(entityInterceptor!

=null?

sessionFactory.openSession(entityInterceptor):

sessionFactory.openSession());//UsesameSessionforfurtherHibernateactionswithinthetransaction.//Threadobjectwillgetremovedbysynchronizationattransactioncompletion.if(TransactionSynchronizationManager.isSynchronizationActive()){//We'rewithinaSpring-managedtransaction,possiblyfromJtaTransactionManager.logger.debug("RegisteringSpringtransactionsynchronizationfornewHibernateSession");SessionHolderholderToUse=sessionHolder;if(holderToUse==null){holderToUse=newSessionHolder(session);}else{holderToUse.addSession(session);}if(TransactionSynchronizationManager.isCurrentTransactionReadOnly()){session.setFlushMode(FlushMode.NEVER);}TransactionSynchronizationManager.registerSynchronization(newSpringSessionSynchronization(holderToUse,sessionFactory,jdbcExceptionTranslator,true));holderToUse.setSynchronizedWithTransaction(true);if(holderToUse!

=sessionHolder){TransactionSynchronizationManager.bindResource(sessionFactory,holderToUse);}}else{//NoSpringtransactionmanagementactive->tryJTAtransactionsynchronization.registerJtaSynchronization(session,sessionFactory,jdbcExceptionTranslator,sessionHolder);}//CheckwhetherweareallowedtoreturntheSession.if(!

allowCreate&&!

isSessionTransactional(session,sessionFactory)){closeSession(session);thrownewIllegalStateException("NoHibernateSessionboundtothread,"+"andconfigurationdoesnotallowcreationofnon-transactionalonehere");}returnsession;}

其实上面一大堆的代码中,我们只需要关注这一句:

SessionHoldersessionHolder=(SessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);记住TransactionSynchronizationManager类和SessionHolder类

好了,说了一大堆DAO,下面正式介绍OpenSessionInViewFilter

下面是OpenSessionInViewFilter中主要的方法doFilterInternal:

[java]viewplaincopy?

protectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{SessionFactorysessionFactory=lookupSessionFactory(request);booleanparticipate=false;if(isSingleSession()){//singlesessionmodeif(TransactionSynchronizationManager.hasResource(sessionFactory)){//DonotmodifytheSession:

justsettheparticipateflag.participate=true;}else{logger.debug("OpeningsingleHibernateSessioninOpenSessionInViewFilter");Sessionsession=getSession(sessionFactory);TransactionSynchronizationManager.bindResource(sessionFactory,newSessionHolder(session));}}else{//deferredclosemodeif(SessionFactoryUtils.isDeferredCloseActive(sessionFactory)){//Donotmodifydeferredclose:

justsettheparticipateflag.participate=true;}else{SessionFactoryUtils.initDeferredClose(sessionFactory);}}try{filterChain.doFilter(request,response);}finally{if(!

participate){if(isSingleSession()){//singlesessionmodeSessionHoldersessionHolder=(SessionHolder)TransactionSynchronizationManager.unbindResource(sessionFactory);logger.debug("ClosingsingleHibernateSessioninOpenSessionInViewFilter");closeSession(sessionHolder.getSession(),sessionFa

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 英语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1