錯誤代碼:
org.
springframework.
dao.
InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode
(FlushMode.
NEVER) - turn your Session into FlushMode.
AUTO or remove
'readOnly' marker from transaction definition
錯誤原因:
OpenSessionInViewFilter在getSession的時候,會把獲取回來的session的flush mode 設(shè)為FlushMode.NEVER。然后把該sessionFactory綁定到TransactionSynchronizationManager,使request的整個過程都使用同一個session,在請求過后再解除該sessionFactory的綁定,最后
closeSessionIfNecessary根據(jù)該session是否已和transaction綁定來決定是否關(guān)閉session。在這個過程中,若HibernateTemplate 發(fā)現(xiàn)自當(dāng)前session有不是readOnly的transaction,就會獲取到FlushMode.AUTO Session,使方法擁有寫權(quán)限。
也即是,如果有不是readOnly的transaction就可以由Flush.NEVER轉(zhuǎn)為Flush.AUTO,擁有insert,update,delete操作權(quán)限,如果沒有transaction,并且沒有另外人為地設(shè)flush model的話,則doFilter的整個過程都是Flush.NEVER。所以受transaction保護的方法有寫權(quán)限,沒受保護的則沒有。
參考文章:
http://calvin.blog.javascud.org/post/46.htm
解決辦法:
采用spring的事務(wù)聲明,使方法受transaction控制
<bean id="baseTransaction"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="proxyTargetClass" value="true"/>
<property name="transactionAttributes">
<props>
<prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="find*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="load*">PROPAGATION_REQUIRED,readOnly</prop>
<prop key="save*">PROPAGATION_REQUIRED</prop>
<prop key="add*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="remove*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<bean id="userService" parent="baseTransaction">
<property name="target">
<bean class="com.phopesoft.security.service.impl.UserServiceImpl"/>
</property>
</bean>