Hibernate 容許對關聯對象、屬性進行延遲加載,可是必須保證延遲加載的操做限於同一個 Hibernate Session 範圍以內進行。若是 Service 層返回一個啓用了延遲加載功能的領域對象給 Web 層,當 Web 層訪問到那些須要延遲加載的數據時,因爲加載領域對象的 Hibernate Session 已經關閉,這些致使延遲加載數據的訪問異常。而Spring爲咱們提供的OpenSessionInViewFilter過濾器爲咱們很好的解決了這個問 題。OpenSessionInViewFilter的主要功能是使每一個請求過程綁定一個 Hibernate Session,即便最初的事務已經完成了,也能夠在 Web 層進行延遲加載的操做。OpenSessionInViewFilter 過濾器將 Hibernate Session 綁定到請求線程中,它將自動被 Spring 的事務管理器探測到。web
看過OpenSessionInViewFilter之後就知道,OpenSessionInViewFilter的getSession方法中會對session的flushMode設定一個默認爲NEVER的值。spring
我在用STRUCT2的時候只要在web.xml中配上下面的配置就能夠了,不過我發現我在Spring MVC中這樣配發現並無起做用。
express
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>flushMode</param-name>
<param-value>AUTO</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>session
這時候解決辦法有兩個:
1:繼承OpenSessionInViewFilter,並覆蓋getSession,設施flushMode 爲AUTO
2:經過spring的事務管理Hibernate的sessionFactory,對不一樣的數據操做做事務的隔離及限制
由於反正都要用到spring做事務管理,因此我在項目中採用了第二種方法,而後我在spring的配置文件中這樣配mvc
<bean id="txManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(* com.pyp.workflow.dao.impl.*.*(..))" />
<aop:advisor pointcut-ref="bussinessService" advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="get*" read-only="false" propagation="NOT_SUPPORTED" />
<tx:method name="find*" propagation="NOT_SUPPORTED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>app
而後配完以後並無用,事務沒有生產。這就挺奇怪了的,我搞了很久才查到ide
你們先看下面配置,spring中自動掃包的url
<context:component-scan base-package="com">
spa
看過spring的參考手冊的朋友都會這樣配置,由於省事,一句話能夠自動把com包低下的全部帶annotation註解的類都實例化並配好了。因此習慣的也在springMVC中也做了這樣的配置。hibernate
但若是這樣簡單的配置會致使剛纔spring的事務配置失效緣由:
實例化@Controller類時,Spring會自動把關聯的@Service(此@Service已作了@Transaction事務註解)類實例化,此時事務並未生效,致使@Transaction註解無效,事務未被註冊,所以須要把@Controller和其它的@Service,@Components,@Reposity等分開實例化,在事務生效後,而且其它組件都實例化完成後,@Controller最後實例化。因此在SpringMVC的配置文件中
<context:component-scan base-package="com.*.*.*">
這個配置要配到Controller(對應struct2中的action)這一層的根目錄下。這樣就能夠解決這個問題。
還有一種解決辦法就是在spring中的配置文件中這樣配
<!-- 掃描com及子包,自動實例化帶@註釋的實例,這裏排除@Controller,全部controller的實例化在 mvc-config中完成 -->
<context:component-scan base-package="com">
<context:exclude filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
在spring mvc的配置文件這樣配
<!-- 掃描com及子包,自動實例化帶@controller註釋的實例,
因爲實例化controller時會對controller關聯的Service類一同實例化,因此這裏須要排除@Service
-->
<context:component-scan base-package="com">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>
這樣也能夠解決這個問題