有些spring相關的知識點之前一直沒有仔細研究:比如spring的事務,並不是沒有使用,也曾經簡單的在某些需要事務處理的方法上通過增加事務註解來實現事務功能,僅僅是跟隨使用(甚至並未測試過事務的正確性),至於如何在專案中配置事務,如何才能將事務寫正確,事務的其它的一些原理性的東西從未花時間研究。最近同事正好丟擲了乙個問題,藉此機會學習了一遍。
問題一:增加了readonly=true的事務中包含寫操作,為什麼線上執行這段**是正常的呢?
@transactional(readonly = true我為什麼對這個問題感興趣?)
public
integer getuid(string key, string type)
開始寫單元測試:
@autowired測試結果顯示正常,與上面提到的不允許進行寫操作的觀點相反,於是想起典型的事務生效問題。private
ikeygeneratordao keygeneratordao;
@transactional(readonly=true
)
public
integer getid(string key, string type)
@transactional
public
integer getuid(string key, string type)
@test
public
void
testcreateguid()
挖的第乙個坑:如果事務採用的是cglib動態**,呼叫的方法與事務方法處在同乙個類中事務不生效。
@autowired測試結果顯示也是正常,於是想確認下事務到底是否生效,加入異常以測試資料是否回滾,修改**如下:private
keygeneratorservice keyservice;
@test
public
void
testcreateguid2()
@transactional測試結果顯示事務回滾正常,可以排除事務環境配置問題。public
integer getuid3(string key, string type)
挖的第二個坑:做測試一定要與原問題**盡量保持一致,否則會產生其它的不明原因影響判斷。通過對比原問題的**發現我寫的測試**與問題**有區別,readonly是加在包含有寫操作的方法上,而我的是兩個方法,只有在讀的方法上增加了readonly,於時再次修改**:
@transactional(readonly = true)
public
integer getuid4(string key, string type)
@autowiredprivate
ikeygeneratordao keygeneratordao;
@transactional(readonly = true
)
public
integer getuid(string key, string type)
public
string genordercode(date orderdate)
@test測試結果居然是正常的,這與線上執行的結果相同,後面經同事提醒,這又是乙個不正確使用事務的案例。public
void
testcreateguid3()
挖的第三個坑:當呼叫乙個類的非事務方法且這個非事務方法內部呼叫了本類自身的事務方法,那麼事務也不會生效。
問題二:下面的**可以實現事務回滾嗎?
@transactionalpublic
integer getuid2(string key, string type)
@transactional
public
string genordercode(date orderdate)
catch
(exception ex)
return
null
; }
@test執行測試**,發現可以成功提交,但資料是不完整的,因為更新操作沒有完成。為什麼會是這樣的呢?因為預設的propagation.required指明多個操作處於乙個事務中,由於genordercode有異常處理,所以即使getuid2中發生異常,系統也會認定提交是合法的,因此會出現插入操作正常更新不正常但事務正常提交並不回滾的情況。public
void
testcreateguid3()
如果顯示指定propagation.requires_new呢?
@transactional(propagation=propagation.requires_new)再執行相同的測試,資料正常回滾,這裡提供兩張圖,可以看的清楚些(因為常用的就這兩種,其它的有興趣可以多多研究)public
integer getuid2(string key, string type)
通過事務的兩個小問題,總結出解決問題的一些小技巧或者叫經驗:發現問題之後,不要侷限於某個點,最好根據上下文來結合分析,比如問題一的readonly可寫入,單看那段**很難找出合理的解釋,只有結合前後端呼叫才能找出根本原因。寫單元測試盡量寫相同的**,否則有可能會出現一些干擾項影響判斷。學習呢,有時間盡量學的全點,比如@transactional這個註解,除了readonly還有propagation等等。
**:
兩個與spring事務相關的問題
有些spring相關的知識點之前一直沒有仔細研究 比如spring的事務,並不是沒有使用,也曾經簡單的在某些需要事務處理的方法上通過增加事務註解來實現事務功能,僅僅是跟隨使用 甚至並未測試過事務的正確性 至於如何在專案中配置事務,如何才能將事務寫正確,事務的其它的一些原理性的東西從未花時間研究。最近...
Adobe Illustrator的兩個問題
adobe illustrator cs6卡的問題 卡的時候,關掉並清ai的快取,重新開啟,速度能好一點。另外乙個小方法 ctrl y,進入輪廓編輯模式,編輯的速度會快一些。另存的pdf檔案過大的問題 預設儲存的pdf的話,將近150m,通過郵箱時傳送不出去的,可以用下邊的這個方法來解決 匯出後不到...
spring兩個重要屬性
1.lazy init 以上兩個bean,乙個lazy init屬性為true,乙個為false,由什麼區別呢 當ioc容器啟動時,service2會例項化,而service1則不會 但是但容器例項化service2時,service1也被例項化了,為什麼呢,因為service2需要它。也就是說la...