Write operations are not allowed in read-only mode (FlushMode.MANUAL):

轉載自:http://blog.csdn.net/cpf929/article/details/18800147


錯誤信息如下:

ERROR 2014-01-26 19:38:38,504  [org.apache.struts2.dispatcher.Dispatcher] - <Exception occurred during processing request: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.>
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition.
at org.springframework.orm.hibernate3.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1175)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:685)
at org.springframework.orm.hibernate3.HibernateTemplate$12.doInHibernate(HibernateTemplate.java:1)
at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:406)
at org.springframework.orm.hibernate3.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:374)
at org.springframework.orm.hibernate3.HibernateTemplate.save(HibernateTemplate.java:683)

問題只讀模式下(FlushMode.NEVER/MANUAL)寫操作不被允許:把你的Session改成FlushMode.COMMIT/AUTO或者清除事務定義中的readOnly標記。

原因:在Spring的聲明事務管理中,有如下配置:

[html] view plaincopy在CODE上查看代碼片派生到我的代碼片
  1. <tx:attributes>  
  2.              <!-- 指定哪些方法需要加入事務  -->   
  3.               
  4.              <tx:method name="save*" propagation="REQUIRED" />   
  5.   
  6.             <tx:method name="delete*" propagation="REQUIRED" />   
  7.   
  8.             <tx:method name="update*" propagation="REQUIRED" />   
  9.   
  10.             <!-- read-only="true":其餘方法只讀格式,加強其安全性 -->   
  11.   
  12.             <tx:method name="*" read-only="true" propagation="NOT_SUPPORTED" />   
  13.         </tx:attributes>  

而我保存數據的方法名寫成了  register();所以會匹配到最後一個,只讀模式。

網上關於這個問題的解釋:

錯誤原因:
OpenSessionInViewFilter在getSession的時候,會把獲取回來的session的flush mode 設爲FlushMode.NEVER。然後把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過後再解除該sessionFactory的綁定,最後closeSessionIfNecessary根據該session是否已和transaction綁定來決定是否關閉session。在這個過程中,若HibernateTemplate 發現自當前session有不是readOnly的transaction,就會獲取到FlushMode.AUTO Session,使方法擁有寫權限。也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉爲Flush.AUTO,擁有insert,update,delete操作權限,如果沒有transaction,並且沒有另外人爲地設flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction(聲明式的事務)保護的方法有寫權限,沒受保護的則沒有。

解決方法:

web.xml配置裏添加
<filter>
<filter-name>OpenSessionInViewFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
<init-param>
<param-name>sessionFactoryBeanName</param-name>
<param-value>sessionFactory</param-value>
</init-param>
<init-param>
<param-name>singleSession</param-name>
<param-value>true</param-value> 
</init-param>
<init-param>
<param-name> flushMode </param-name>
<param-value>AUTO </param-value> 
</init-param>
</filter>
// 。。

然後還要再事務方法那刷新flush(),否則不會立刻存儲進數據庫

  this.getHibernateTemplate().save(。。);
  getHibernateTemplate().flush() ;


還有一種方法就是直接不用這個過濾器.


<filter-mapping>
<filter-name>OpenSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

如果在交給spring 管理的情況下,在beans.xml 裏的配置

<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<aop:config>
<aop:pointcut id="bussinessService"
expression="execution(* com.fan.service.base.*.*(..))" />
<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*" read-only="false" propagation="NOT_SUPPORTED"/>
<tx:method name="save*" propagation="REQUIRED"/> // 如果不把save update delete都配置上,
<tx:method name="update*" propagation="REQUIRED"/> //這些操作會無效
<tx:method name="delete*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>


發佈了86 篇原創文章 · 獲贊 13 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章