學(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ù)管理。概覽如下:
事務(wù)四大特性:
1.原子性(Atomicity)
原子性是指事務(wù)是一個不可分割的工作單位梦裂,事務(wù)中的操作要么都發(fā)生似枕,要么都不發(fā)生。
- 一致性(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)證。