概念:從這一點設置的時間點開始(時間點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類的事務屬性詳解
-
PROPAGATION_REQUIRED: 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇。
-
PROPAGATION_SUPPORTS: 支持當前事務,如果當前沒有事務,就以非事務方式執行。
-
PROPAGATION_MANDATORY: 支持當前事務,如果當前沒有事務,就拋出異常。
-
PROPAGATION_REQUIRES_NEW: 新建事務,如果當前存在事務,把當前事務掛起。
-
PROPAGATION_NOT_SUPPORTED:以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
-
PROPAGATION_NEVER: 以非事務方式執行,如果當前存在事務,則拋出異常。
-
PROPAGATION_NESTED: 支持當前事務,如果當前事務存在,則執行一個嵌套事務,如果當前沒有事務,就新建一個事務。
<tx:method/>
有關的設置
屬性 | 是否需要? | 默認值 | 描述 |
---|---|---|---|
name |
是 | 與事務屬性關聯的方法名。通配符(*)可以用來指定一批關聯到相同的事務屬性的方法。如: |
|
propagation |
不 | REQUIRED | 事務傳播行為 |
isolation |
不 | DEFAULT | 事務隔離級別 |
timeout |
不 | -1 | 事務超時的時間(以秒為單位) |
read-only |
不 | false | 事務是否只讀? |
rollback-for |
不 | 將被觸發進行回滾的 |
|
no-rollback-for |
不 | 不 被觸發進行回滾的 |