1. 程式人生 > >Spring read-only="true" 只讀事務的

Spring read-only="true" 只讀事務的

blank 常見 con string 3.2 action summary aspectj pointcut

概念:從這一點設置的時間點開始(時間點a)到這個事務結束的過程中,其他事務所提交的數據,該事務將看不見!(查詢中不會出現別人在時間點a之後提交的數據)

應用場合:

如果你一次執行單條查詢語句,則沒有必要啟用事務支持,數據庫默認支持SQL執行期間的讀一致性;
如果你一次執行多條查詢語句,例如統計查詢,報表查詢,在這種場景下,多條查詢SQL必須保證整體的讀一致性,否則,在前條SQL查詢之後,後條SQL查詢之前,數據被其他用戶改變,則該次整體的統計查詢將會出現讀數據不一致的狀態,此時,應該啟用事務支持。
【註意是一次執行多次查詢來統計某些信息,這時為了保證數據整體的一致性,要用只讀事務】

怎樣設置:

對於只讀查詢,可以指定事務類型為readonly,即只讀事務。
由於只讀事務不存在數據的修改,因此數據庫將會為只讀事務提供一些優化手段,例如Oracle對於只讀事務,不啟動回滾段,不記錄回滾log。

(1)在JDBC中,指定只讀事務的辦法為: connection.setReadOnly(true);

(2)在Hibernate中,指定只讀事務的辦法為: session.setFlushMode(FlushMode.NEVER);
此時,Hibernate也會為只讀事務提供Session方面的一些優化手段

(3)在Spring的Hibernate封裝中,指定只讀事務的辦法為: bean配置文件中,prop屬性增加“readOnly”

或者用註解方式@Transactional(readOnly=true)
【 if the transaction is marked as read-only, Spring will set the Hibernate Session’s flush mode to FLUSH_NEVER,
and will set the JDBC transaction to read-only】也就是說在Spring中設置只讀事務是利用上面兩種方式

在將事務設置成只讀後,相當於將數據庫設置成只讀數據庫,此時若要進行寫的操作,會出現錯誤


//測試get開頭的只讀屬性,寫數據會保錯的情況

public Object getDemoTestTransaction() {
TOmOrderPlaneItemExample example = new TOmOrderPlaneItemExample();
example.createCriteria().andOrderCodeEqualTo("422751536598089068544");
List<TOmOrderPlaneItem> selectByExample = tOmOrderPlaneItemMapper.selectByExample(example );
TOmOrderPlaneItem record = new TOmOrderPlaneItem();
record.setOrderCode("123");
record.setPaymentMode("1");
tOmOrderPlaneItemMapper.insert(record );
return selectByExample;
}

單元測試:

@Test
public void test_Transaction() {
Object demoTestTransaction = planeService.getDemoTestTransaction();
log.debug("===="+JSON.toJSONString(demoTestTransaction));
}

貼一段配置事務的xml:


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

<tx:annotation-driven transaction-manager="transactionManager"/>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<aop:config>
<aop:pointcut id="ServiceMethods"
expression="execution(* com.baidu.business.service..*Service.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="ServiceMethods"/>
</aop:config>

<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<tx:method name="query*" read-only="true"/>
<tx:method name="count*" read-only="true"/>
<tx:method name="select*" read-only="true"/>
<tx:method name="search*" read-only="true"/>
<tx:method name="has*" read-only="true"/>
<tx:method name="export*" read-only="true"/>
<tx:method name="is*" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>

</beans>

註意以get、find開頭的字段,都是可讀的,也可以通過@Transactional(readOnly = false) 來覆蓋掉配置文件的屬性,這樣就能插入數據了

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 讀取操作 -->
<tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
<tx:method name="get*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
<tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>
</tx:attributes>
</tx:advice>

spring中PROPAGATION類的事務屬性詳解

  1. PROPAGATION_REQUIRED: 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。

  2. PROPAGATION_SUPPORTS: 支持當前事務,如果當前沒有事務,就以非事務方式執行。

  3. PROPAGATION_MANDATORY: 支持當前事務,如果當前沒有事務,就拋出異常。

  4. PROPAGATION_REQUIRES_NEW: 新建事務,如果當前存在事務,把當前事務掛起。

  5. PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

  6. PROPAGATION_NEVER: 以非事務方式執行,如果當前存在事務,則拋出異常。

  7. PROPAGATION_NESTED: 支持當前事務,如果當前事務存在,則執行一個嵌套事務,如果當前沒有事務,就新建一個事務。

<tx:method/> 有關的設置

屬性是否需要?默認值描述
name

與事務屬性關聯的方法名。通配符(*)可以用來指定一批關聯到相同的事務屬性的方法。如:‘get*‘‘handle*‘‘on*Event‘等等。

propagation REQUIRED 事務傳播行為
isolation DEFAULT 事務隔離級別
timeout -1 事務超時的時間(以秒為單位)
read-only false 事務是否只讀?
rollback-for

將被觸發進行回滾的 Exception(s);以逗號分開。 如:‘com.foo.MyBusinessException,ServletException‘

no-rollback-for

被觸發進行回滾的 Exception(s);以逗號分開。 如:‘com.foo.MyBusinessException,ServletException‘

Spring read-only="true" 只讀事務的