假設(shè)在你的應(yīng)用中Hibernate是通過(guò)spring 來(lái)管理它的session.如果在你的應(yīng)用中沒(méi)有使用OpenSessionInViewFilter或者OpenSessionInViewInterceptor。session會(huì)在transaction結(jié)束后關(guān)閉。
如果你采用了spring的聲明式事務(wù)模式,它會(huì)對(duì)你的被代理對(duì)象的每一個(gè)方法進(jìn)行事務(wù)包裝(AOP的方式)。如下:

 

 <bean id="txProxyTemplate" abstract="true"
        class
="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        
<property name="transactionManager" ref="transactionManager"/>
        
<property name="transactionAttributes">
            
<props>
                
<prop key="save*">PROPAGATION_REQUIRED</prop>
                
<prop key="remove*">PROPAGATION_REQUIRED</prop>
                
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
            
</props>
        
</property>
    
</bean>

    
<bean id="manager" parent="txProxyTemplate">
        
<property name="target">
            
<bean class="org.appfuse.service.impl.BaseManager">
                
<property name="dao" ref="dao"/>
            
</bean>
        
</property>
    
</bean>

目標(biāo)類org.appfuse.service.impl.BaseManager 的  save *方法的事務(wù)類型PROPAGATION_REQUIRED  ,remove* 方法的事務(wù)類型PROPAGATION_REQUIRED
其他的方法的事務(wù)類型是PROPAGATION_REQUIRED,readOnly。
所以給你的感覺(jué)是調(diào)用這個(gè)名為“manager”的bean的方法之后session就關(guān)掉了。
如果應(yīng)用中使用了OpenSessionInViewFilter或者OpenSessionInViewInterceptor,所有打開(kāi)的session會(huì)被保存在一個(gè)線程變量里。在線程退出前通過(guò)
OpenSessionInViewFilter或者OpenSessionInViewInterceptor斷開(kāi)這些session。 為什么這么做?這主要是為了實(shí)現(xiàn)Hibernate的延遲加載功能。基于一個(gè)請(qǐng)求
一個(gè)hibernate session的原則。

spring中對(duì)OpenSessionInViewFilter的描述如下:
它是一個(gè)Servlet2.3過(guò)濾器,用來(lái)把一個(gè)Hibernate Session和一次完整的請(qǐng)求過(guò)程對(duì)應(yīng)的線程相綁定。目的是為了實(shí)現(xiàn)"Open Session in View"的模式。
例如: 它允許在事務(wù)提交之后延遲加載顯示所需要的對(duì)象。

這個(gè)過(guò)濾器和 HibernateInterceptor 有點(diǎn)類似:它是通過(guò)線程實(shí)現(xiàn)的。無(wú)論是沒(méi)有事務(wù)的應(yīng)用,還是有業(yè)務(wù)層事務(wù)的應(yīng)用(通過(guò)HibernateTransactionManager 或
JtaTransactionManager的方式實(shí)現(xiàn))它都適用。在后一種情況下,事務(wù)會(huì)自動(dòng)采用由這個(gè)filter綁定的Session來(lái)進(jìn)行相關(guān)的操作以及根據(jù)實(shí)際情況完成提交操作。

警告: 如果在你的應(yīng)用中,一次請(qǐng)求的過(guò)程中使用了單一的一個(gè)HIbernate Session,在這種情況下,采用這個(gè)filter會(huì)產(chǎn)生一些以前沒(méi)遇到的問(wèn)題。特別需要注意的是通過(guò)
Hibernate Session重新組織持久化對(duì)象之間關(guān)系的相關(guān)操作需要在請(qǐng)求的最開(kāi)始進(jìn)行。以免與已經(jīng)加載的相同對(duì)象發(fā)生沖突。

或者,我們可以通過(guò)指定"singleSession"="false"的方式把這個(gè)過(guò)濾器調(diào)到延期關(guān)閉模式。這樣在一次請(qǐng)求的過(guò)程中不會(huì)使用一個(gè)單一的Session.每一次數(shù)據(jù)訪問(wèn)或事務(wù)相關(guān)
操作都使用屬于它自己的session(有點(diǎn)像不使用Open Session in View).這些session都被注冊(cè)成延遲關(guān)閉模式,即使是在這一次的請(qǐng)求中它相關(guān)操作已經(jīng)完成。

"一次請(qǐng)求一個(gè)session" 對(duì)于一級(jí)緩存而言很有效,但是這樣可以帶來(lái)副作用。例如在saveOrUpdate的時(shí)候或事物回滾之后,雖然它和“no Open Session in View”同樣安全。
但是它卻允許延遲加載。

它會(huì)在spring的web應(yīng)用的上下文根中查找Session工廠。它也支持通過(guò)在web.xml中定義的“SessionFactoryBeanName”的init-param元素 指定的Session工廠對(duì)應(yīng)的bean的
名字來(lái)查找session工廠。默認(rèn)的bean的名字是"sessionFactory".他通過(guò)每一次請(qǐng)求查找一次SessionFactory的方式來(lái)避免由初始化順序引起的問(wèn)題(當(dāng)使用ContextLoaderServlet
來(lái)集成spring的時(shí)候 ,spring 的應(yīng)用上下文是在這個(gè)filter 之后才被初始化的)。

默認(rèn)的情況下,這個(gè)filter 不會(huì)同步Hibernate Session.這是因?yàn)樗J(rèn)為這項(xiàng)工作是通過(guò)業(yè)務(wù)層的事務(wù)來(lái)完成的。而且HibernateAccessors 的FlushMode為FLUSH_EAGER.如果你
想讓這個(gè)filter在請(qǐng)求完成以后同步session.你需要覆蓋它的closeSession方法,在這個(gè)方法中在調(diào)用父類的關(guān)閉session操作之前同步session.此外你需要覆蓋它的getSession()
方法。返回一個(gè)session它的FlushMode 不是默認(rèn)的FlushMode.NEVER。需要注意的是getSession()和closeSession()方法只有在single session的模式中才被調(diào)用。

在myfaces的wiki里提供了OpenSessionInViewFilter的一個(gè)子類如下:

public class OpenSessionInViewFilter extends org.springframework.orm.hibernate3.support.OpenSessionInViewFilter {
       
        
/**
         * we do a different flushmode than in the codebase
         * here
         
*/

        
protected Session getSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException {
                Session session 
= SessionFactoryUtils.getSession(sessionFactory, true);
                session.setFlushMode(FlushMode.COMMIT);
                
return session;
        }

        
/**
         * we do an explicit flush here just in case
         * we do not have an automated flush
         
*/

        
protected void closeSession(Session session, SessionFactory factory) {
                session.flush();
                
super.closeSession(session, factory);
        }

}