天天看點

【spring架構】spring使用Annotation進行聲明式事務管理

聲明式的事務管理

a)事務加在dao層還是service層?

userservice調了userdao,調了它的save方法,而userdao它會去通路資料庫。

在dao裡面,事務的還是就是save的開始,事務的結束就是save的結束,這是最直覺的。也可以用aop來寫,spring已經給你寫好了。

那麼事物的邊界(begintransaction()事務開始和事物結束gettransaction().commit())加在哪裡比較好呢?

dao一般都是固定的單一的crud,也就是核心的事務操作,像加日志這種事務的準備或者錦上添花的東西我們可以加在service層。

我們在這裡用一個例子說明:

在資料庫建立一個日志資訊表t_log,我們準備在save事務之後向資料庫添加一個日志資訊,來記錄user的存儲情況。

首先回顧一下userdao的存儲:

user.java:

userdaoimpl.java:

之後我添加了日志:

logdaoimpl.java:

别忘記在配置檔案beans.xml中加log實體類<value>cn.edu.hpu.model.log</value>:

現在我們需要将日志添加事務放在存儲user的後面,是放在dao裡面好還是service裡面好呢?按照前面說的,加載service裡面比較合适:

測試:

測試結果:

class cn.edu.hpu.service.userservice

hibernate: insert into user (name) values (?)

add success!!

hibernate: insert into t_log (msg) values (?)

log add success!!

log日志添加成功!

這都是我們是手動添加的事務開始于結束(s.begintransaction();與s.gettransaction().commit();),那麼如何用spring的機制來自動添加事務呢?下面先說一下annotation的實作:

b)annotation

i.加入annotation.xsd(關于tx的)

ii.加入txmanager bean

因為你結合的是hibernate,是以事務管理也是使用hibernate的事務管理。

所用類org.springframework.orm.hibernate3.hibernatetransactionmanager

hibernatetransactionmanager就是在方法之前加點東西,方法之後加點東西,也就是是一個aspect切面類,應用了aop。你讓它管理事務,必須要告訴他資料庫的連接配接是誰,采取的方式是将sessionfactory注進去:

iii.<tx:annotation-driven

iv.在需要事務的方法上加:@transactional

例如你需要在add方法上有事務,那就在add方法上加@transactional

它會自動在前後幫你加上關于業務的事務邏輯

這個時候user的save和log的save裡面的s.begintransaction();與s.gettransaction().commit();就不用寫了

v.需要注意,使用sessionfactory.getcurrentsession 不要使用opensession

結果存儲成功,說明@transactional注解起作用了。而且如果@transactional注解的方法的事務runtime時出了問題,會自動復原,測試:

在log的save後面加一個runtimeexception異常:

結果:

沒有将log添加進去,說明事務復原了。這是spring對于hibernate事務的管理。通常情況下add方法裡面都要加try-catch包圍的,有了上述管理,就不用try-catch了。

3.@transactional 有關的設定

@transactional 注解是用來指定接口、類或方法必須擁有事務語義的中繼資料。 如:“當一個方法開始調用時就開啟一個新的隻讀事務,并停止掉任何現存的事務”。 預設的 @transactional 設定如下: 

事務傳播設定是 propagation_required

事務隔離級别是 isolation_default

事務是 讀/寫

事務逾時預設是依賴于事務系統的,或者事務逾時沒有被支援。

任何 runtimeexception 将觸發事務復原,但是任何 checked exception 将不觸發事務復原

這些預設的設定當然也是可以被改變的。 @transactional 注解的各種屬性設定總結如下: 

表 9.3. @transactional 注解的屬性

屬性 類型 描述 

propagation  枚舉型:propagation  可選的傳播性設定 

isolation 枚舉型:isolation  可選的隔離性級别(預設值:isolation_default) 

readonly 布爾型 讀寫型事務 vs. 隻讀型事務 

timeout int型(以秒為機關) 事務逾時 

rollbackfor 一組 class 類的執行個體,必須是throwable的子類一組異常類,遇到時必須進行復原。預設情況下checked exceptions不進行復原,僅unchecked exceptions(即runtimeexception的子類)才進行事務復原。 

rollbackforclassname 一組class類的名字,必須是throwable的子類 一組異常類名,遇到時 必須進行復原 

norollbackfor 一組 class 類的執行個體,必須是throwable的子類一組異常類,遇到時必須不復原。 

norollbackforclassname 一組class類的名字,必須是throwable 的子類 一組異常類,遇到時 必須不復原 

在寫代碼的時候,不可能對事務的名字有個很清晰的認識,這裡的名字是指會在事務螢幕(比如weblogic的事務管理器)或者日志輸出中顯示的名字, 對于聲明式的事務設定,事務名字總是全限定名+"."+事務通知的類的方法名。比如businessservice類的handlepayment(..)方法啟動了一個事務,事務的名稱是:

com.foo.businessservice.handlepayment

最常用的是@transactional(propagation=propagation.required) 

是propagation一堆屬性中唯一一個需要記住的。

意思是在目前的這個環境中,别人調我這個方法,比如說已經有了一個transaction了,就用原來那個,把自己作為transaction的一部分加進去就行了,如果沒有就建立一個新的。

轉載請注明出處:http://blog.csdn.net/acmman/article/details/44651921