關(guān)于@Transactional注解漫談事務(wù)_2020.05.07

學(xué)習(xí)基于記錄走敌,而不止于記錄。

希望自己能堅持下去~

0.寫在前面

import org.springframework.transaction.annotation.Transactional
@Transactional這個注解開發(fā)中很常見很常用,但是關(guān)于這個注解還可以展開聊一聊spring中的事務(wù)處理。

spring boot版本:2.0.8.RELEASE

1.關(guān)于事務(wù)

??事務(wù)管理是應(yīng)用系統(tǒng)開發(fā)中必不可少的一部分送滞。Spring 為事務(wù)管理提供了豐富的功能支持钧大。Spring 事務(wù)管理分為編碼式聲明式的兩種方式瘤运。編程式事務(wù)指的是通過編碼方式實(shí)現(xiàn)事務(wù)窍霞;聲明式事務(wù)基于 AOP,將具體業(yè)務(wù)邏輯與事務(wù)處理解耦。聲明式事務(wù)管理使業(yè)務(wù)代碼邏輯不受污染, 因此在實(shí)際使用中聲明式事務(wù)用的比較多拯坟。聲明式事務(wù)有兩種方式但金,一種是在配置文件(xml)中做相關(guān)的事務(wù)規(guī)則聲明,另一種是基于@Transactional 注解的方式郁季。注釋配置是目前流行的使用方式冷溃,因此本文將著重介紹基于@Transactional 注解的事務(wù)管理。概覽如下:

image.png

事務(wù)四大特性:
1.原子性(Atomicity)
原子性是指事務(wù)是一個不可分割的工作單位梦裂,事務(wù)中的操作要么都發(fā)生似枕,要么都不發(fā)生。

  1. 一致性(Consistency)
    事務(wù)必須使數(shù)據(jù)庫從一個一致性狀態(tài)變換到另外一個一致性狀態(tài)年柠。(數(shù)據(jù)不被破壞)

3.隔離性(Isolation)
事務(wù)的隔離性是指一個事務(wù)的執(zhí)行不能被其他事務(wù)干擾.

4.持久性(Durability)
持久性是指一個事務(wù)一旦被提交凿歼,它對數(shù)據(jù)庫中數(shù)據(jù)的改變就是永久性的.即使系統(tǒng)重啟也不會丟失.

2.常規(guī)用法

以spring boot開發(fā)為例,通常在serviceImpl方法上加@Transactional注解冗恨,即可實(shí)現(xiàn)事務(wù)控制答憔。

疑惑:為什么要在service層加事務(wù)控制,而不是Dao層掀抹?

如果事務(wù)直接在Dao層聲明虐拓,持久層每一次操作就會產(chǎn)生一次事務(wù)提交,無法保證事務(wù)的一致性傲武。而service層編寫邏輯代碼侯嘀,會存在多次持久層操作,在這層使用事務(wù)處理恰到好處谱轨。也有一些事務(wù)會放在controller,但是出于開發(fā)規(guī)范考慮通常都放在service層吠谢。

3.使用細(xì)節(jié)

3.1 數(shù)據(jù)庫必須支持事務(wù)

3.2必須在實(shí)例化spring bean的類中使用

比如我們的service通常會使用@service注解土童,就是為了裝配成為spring bean。

3.3注解的方法必須是public聲明

3.4自我調(diào)用

  • 場景:
    在service層A方法(無注解)調(diào)用B方法(有注解)工坊,直接用this.B(params)献汗,會導(dǎo)致事務(wù)失效。

  • 解決方案
    使用延遲注入@Lazy

@Slf4j
@Service(value = "tUserServiceImpl")
public class TUserServiceImpl implements TUserService {
    @Lazy
    private TUserService tUserService;
}
  • 原因
    這和3.2特性有關(guān)王污,使用延遲注入可以將裝配成spring bean的service層bean注入自身罢吃,然后通過注入的bean來調(diào)用其他方法,而不影響事務(wù)處理了昭齐。

強(qiáng)烈推薦看看這篇文章知乎:玩轉(zhuǎn)Spring —— 消失的事務(wù)尿招,說的很詳細(xì)。
摘錄:
????由于methodA沒有加@Transactional注解,所以代理對象里面就谜,直接就是target.methodA()怪蔑,直接調(diào)用了原來對象的methodA。
????這下就很清晰了丧荐,代理對象的methodA缆瓣,去調(diào)用原來對象的methodA,原來對象的methodA虹统,再去調(diào)用原來對象的methodB弓坞,而原來對象的methodB,是不具有事務(wù)的车荔。事務(wù)只存在于代理對象的methodB. 所以整個方法也就沒有事務(wù)了渡冻。

這下就很清晰了,代理對象的methodA夸赫,去調(diào)用原來對象的methodA菩帝,原來對象的methodA,再去調(diào)用原來對象的methodB茬腿,而原來對象的methodB呼奢,是不具有事務(wù)的。事務(wù)只存在于代理對象的methodB. 所以整個方法也就沒有事務(wù)了切平。

3.5關(guān)于異常

  • 只捕獲而不拋出事務(wù)不會生效
  • 拋出異常必須是RuntimeException握础,自定義或者其他類型的異常,事務(wù)也不生效


    exception_relation.png

那如果我需要自定義異炽财罚回滾禀综,怎么辦?

使用rollbackFor 苔严,聲明為哪些異常進(jìn)行回滾

@Transactional(rollbackFor = [MyException::class])
@Throws(MyException::class)
public void catchThrowsExceptionWithTransactional() {
    try {
        Man man = new Man("1", Woman("1"))
        manRepository.save(man)
        throw new MyException("custom exception")
    } catch (MyException e) {
        throw e
    }
}

3.6事務(wù)傳播定枷,@Transactional(propagation = ?)

  • REQUIRED
    如果沒有就創(chuàng)建一個,如果有届氢,就用當(dāng)前的
  • REQUIRED_NEW
    每次都會創(chuàng)建一個新的欠窒,如果當(dāng)前就有一個,那么會把當(dāng)前的掛起

區(qū)別:
REQUIRED 如果兩個方法共享一個事務(wù)退子,一個需要回滾岖妄,一個需要提交,就會出現(xiàn)UnexpectedRollbackException寂祥;
REQUIRED_NEW 兩個方法都有自己的事務(wù)荐虐,所以不會互相影響。

  • SUPPORTS 如果當(dāng)前有事務(wù)就用丸凭,如果沒有就不用事務(wù)的

  • NESTED 不建議使用福扬,和JDBC版本有關(guān)

3.7Isolation 事務(wù)的隔離,@Transactional(isolation = ?)

  • Dirty read 臟讀: read the uncommitted change of a concurrent transaction.
    A事務(wù)在讀取某一行數(shù)據(jù)的時候腕铸,能夠讀到B事務(wù)還未提交的、對同一行數(shù)據(jù)的修改忧换。
  • Non-repeatable read 不可重復(fù)讀: get different value on re-read of a row if a concurrent transaction updates
    the same row and commits.
    在同一個事務(wù)里恬惯,在T1時間讀取到的某一行的數(shù)據(jù),在T2時間再次讀取同一行數(shù)據(jù)時亚茬,發(fā)生了變化酪耳。后者變化可能是被更新了、消失了刹缝。
  • Phantom read 幻讀: get different rows after re-execution of a range query if another transaction adds or
    removes some rows in the range and commits.
    在同一個事務(wù)里碗暗,用條件A,在T1時間查詢到的數(shù)據(jù)是10行梢夯,但是在T2時間查詢到的數(shù)據(jù)多于10行言疗。需要注意的是,
    和 Nonrepeatable read 不同颂砸,Phantom read 在T1時讀到的數(shù)據(jù)在T2時不會發(fā)生變化噪奄。注意,為何只說比10行多人乓,
    那么比10行少就不是 Phantom read 了嗎勤篮?因?yàn)?Nonrepeatable read 包含了數(shù)據(jù)消失的情況。
隔離等級 臟讀 不可重復(fù)讀 幻讀
READ_UNCOMMITTED 可能發(fā)生 可能發(fā)生 可能發(fā)生
READ_COMMITTED 可能發(fā)生 可能發(fā)生
REPEATABLE_READ 可能發(fā)生
SERIALIZABLE

注意:
雖然SERIALIZABLE可以避免所有異常情況色罚, 但是不建議碰缔,因?yàn)樾侍土恕?/p>

4. 總結(jié)

以上就是對于@Transational事務(wù)注解的一些總結(jié),有一些我已經(jīng)測試過了戳护,但是有部分我只是從其他博客或者學(xué)習(xí)視頻參考過來的金抡,所以得找個時間驗(yàn)證。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腌且,一起剝皮案震驚了整個濱河市梗肝,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铺董,老刑警劉巖统捶,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異柄粹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)匆绣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進(jìn)店門驻右,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崎淳,“玉大人堪夭,你說我怎么就攤上這事。” “怎么了森爽?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵恨豁,是天一觀的道長。 經(jīng)常有香客問我爬迟,道長橘蜜,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任付呕,我火速辦了婚禮计福,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘徽职。我一直安慰自己象颖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布姆钉。 她就那樣靜靜地躺著说订,像睡著了一般。 火紅的嫁衣襯著肌膚如雪潮瓶。 梳的紋絲不亂的頭發(fā)上陶冷,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天,我揣著相機(jī)與錄音筋讨,去河邊找鬼埃叭。 笑死,一個胖子當(dāng)著我的面吹牛悉罕,可吹牛的內(nèi)容都是我干的赤屋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼壁袄,長吁一口氣:“原來是場噩夢啊……” “哼类早!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嗜逻,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤涩僻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后栈顷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逆日,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年萄凤,在試婚紗的時候發(fā)現(xiàn)自己被綠了室抽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡靡努,死狀恐怖坪圾,靈堂內(nèi)的尸體忽然破棺而出晓折,到底是詐尸還是另有隱情,我是刑警寧澤兽泄,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布漓概,位于F島的核電站,受9級特大地震影響病梢,放射性物質(zhì)發(fā)生泄漏胃珍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一飘千、第九天 我趴在偏房一處隱蔽的房頂上張望堂鲜。 院中可真熱鬧,春花似錦护奈、人聲如沸缔莲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痴奏。三九已至,卻和暖如春厌秒,著一層夾襖步出監(jiān)牢的瞬間读拆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工鸵闪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檐晕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓蚌讼,卻偏偏與公主長得像辟灰,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子篡石,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評論 2 359