[英]Spring read-only transaction committing data to the DB
我正在嘗試按照Spring Framework Reference的第11.5.2節實現服務方法的read-only
事務,但事務仍然會自動將數據提交到數據庫。
我正在使用Spring 3.1.0.RELEASE,Hibernate 3.5.5-Final和Oracle 11g Express Edition Release 11.2.0.2.0。 這是我的設置:
建議,切入點,顧問和事務管理器的XML:
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true" />
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myServiceMethods" expression="execution(* my.example.service.*.*(..))" />
<aop:advisor pointcut-ref="myServiceMethods" advice-ref="transactionAdvice" />
</aop:config>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<!-- the sessionFactory bean declaration does not set the -->
<!-- hibernate.connection.autocommit property as either true or false -->
</bean>
服務界面:
package my.example.service;
public interface MyService {
void getFoo();
void bar();
}
服務實施:
package my.example.service.impl;
import my.example.dao.MyDao;
import my.example.domain.MyEntity;
import my.example.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyServiceImpl implements MyService {
@Autowired
private MyDao dao;
public void getFoo() {
MyEntity example = this.dao.getMyEntity(1L);
example.setSomeInteger(2);
example.setSomeString("three");
}
public void bar() {
MyEntity example = this.dao.getMyEntity(4L);
example.setSomeInteger(5);
example.setSomeString("six");
}
}
在調用getFoo()
或bar()
,即使getFoo()
被標記為read-only
,DB也會更新。 但如果我改變這兩行:
<tx:method name="get*" read-only="true" />
<tx:method name="*"/>
至:
<tx:method name="*" read-only="true" />
兩種方法都遵循read-only
屬性,數據不會提交給DB。
這是怎么回事? 我究竟做錯了什么? 我錯過了什么?
我發現為什么read-only
事務被覆蓋。 在web.xml
聲明了一個OpenSessionInViewFilter ,以前的開發人員在加載用戶及其在控制器/接口中的角色時用來阻止LazyInitializationException
。
這是過濾器聲明:
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
我通過配置過濾器來解決這個問題,讓每個事務都使用自己的會話(稱為deferred mode
)。
這是激活deferred mode
的過濾器聲明:
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>
請閱讀過濾器的Javadoc中的NOTE。 我的DAO類擴展了org.springframework.orm.hibernate3.support.HibernateDaoSupport
,並且繼承方法返回的Hibernate Session getSession()
或getSessionFactory().getCurrentSession()
將其flush模式設置為FlushMode.MANUAL
,而不是FlushMode.NEVER
,正如我在閱讀了這個SO答案后所說的那樣。
為什么不在@Transactional
注釋上使用readOnly標志。
使用@Transactional(readOnly=true)
注釋您的方法,並且Hibernate將嘗試以只讀方式執行事務,並且(我認為,您可能想要仔細檢查這一點)如果嘗試寫入將拋出異常。
在這方面,嘗試重新發明輪子毫無意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.