1.事務(wù)的簡(jiǎn)介
java 中spring提供了很好的事務(wù)管理機(jī)制,主要分為編程式事務(wù)和聲明式事務(wù)、
編程式事務(wù)是在代碼里控制事務(wù)的提交與回滾,缺點(diǎn)在于代碼侵入性比較強(qiáng)
try {
//TODO something
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw new InvoiceApplyException("異常失敗");
聲明式事務(wù):基于AOP面向切面的,降低耦合,代碼侵入性很低,所以在實(shí)際開(kāi)發(fā)中聲明式事務(wù)用的比較多,聲明式事務(wù)也有兩種實(shí)現(xiàn)方式,一是基于TX和AOP的xml配置文件方式,第二種就是基于@Transactional注解了
@Transactional
@GetMapping("/test")
public String test() {
int insert = cityInfoDictMapper.insert(cityInfoDict);
}
2.@Transactional注解的使用
@Transactional 可以作用在接口、類、類方法,如果在類上邊配置,又在對(duì)應(yīng)的類方法上邊配置,則類方法里邊的注解會(huì)被類上邊的給覆蓋掉
3.@Transactional注解的屬性
propagation 代表事務(wù)的傳播行為,默認(rèn)值為 Propagation.REQUIRED,其他的屬性信息如下:
(1)Propagation.REQUIRED:如果當(dāng)前存在事務(wù),則加入該事務(wù),如果當(dāng)前不存在事務(wù),則創(chuàng)建一個(gè)新的事務(wù)。( 也就是說(shuō)如果A方法和B方法都添加了注解,在默認(rèn)傳播模式下,A方法內(nèi)部調(diào)用B方法,會(huì)把兩個(gè)方法的事務(wù)合并為一個(gè)事務(wù) )Propagation.SUPPORTS:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則以非事務(wù)的方式繼續(xù)運(yùn)行。
(2)Propagation.MANDATORY:如果當(dāng)前存在事務(wù),則加入該事務(wù);如果當(dāng)前不存在事務(wù),則拋出異常。
(3)Propagation.REQUIRES_NEW:重新創(chuàng)建一個(gè)新的事務(wù),如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。( 當(dāng)類A中的 a 方法用默認(rèn)Propagation.REQUIRED模式,類B中的 b方法加上采用 Propagation.REQUIRES_NEW模式,然后在 a 方法中調(diào)用 b方法操作數(shù)據(jù)庫(kù),然而 a方法拋出異常后,b方法并沒(méi)有進(jìn)行回滾,因?yàn)镻ropagation.REQUIRES_NEW會(huì)暫停 a方法的事務(wù)
(4)Propagation.NOT_SUPPORTED:以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),暫停當(dāng)前的事務(wù)。
(5)Propagation.NEVER:以非事務(wù)的方式運(yùn)行,如果當(dāng)前存在事務(wù),則拋出異常。
(6)Propagation.NESTED :和 Propagation.REQUIRED 效果一樣
4.事務(wù)的隔離級(jí)別
isolation :事務(wù)的隔離級(jí)別,默認(rèn)值為 Isolation.DEFAULT。
事務(wù)的四大特性分別是:原子性、一致性、隔離性、持久性
事務(wù)存在的問(wèn)題:臟讀、幻讀、不可重復(fù)讀
第一種隔離級(jí)別:Read uncommitted(讀未提交)
如果一個(gè)事務(wù)已經(jīng)開(kāi)始寫(xiě)數(shù)據(jù),則另外一個(gè)事務(wù)不允許同時(shí)進(jìn)行寫(xiě)操作,但允許其他事務(wù)讀此行數(shù)據(jù),這樣的話則會(huì)出現(xiàn)事務(wù)B讀取到了事務(wù)A未提交的數(shù)據(jù)
解決了更新丟失,但還是可能會(huì)出現(xiàn)臟讀
第二種隔離級(jí)別:Read committed(讀提交)
如果是一個(gè)讀事務(wù)(線程),則允許其他事務(wù)讀寫(xiě),如果是寫(xiě)事務(wù)將會(huì)禁止其他事務(wù)訪問(wèn)該行數(shù)據(jù),該隔離級(jí)別避免了臟讀,但是可能出現(xiàn)不可重復(fù)讀。
比如事務(wù)A事先讀取了數(shù)據(jù),事務(wù)B緊接著更新了數(shù)據(jù),并提交了事務(wù),而事務(wù)A再次讀取該數(shù)據(jù)時(shí),數(shù)據(jù)已經(jīng)發(fā)生了改變。
解決了更新丟失和臟讀問(wèn)題
第三種隔離級(jí)別:Repeatable read(可重復(fù)讀取)
可重復(fù)讀取是指在一個(gè)事務(wù)內(nèi),多次讀同一個(gè)數(shù)據(jù),在這個(gè)事務(wù)還沒(méi)結(jié)束時(shí),其他事務(wù)不能訪問(wèn)該數(shù)據(jù)(包括了讀寫(xiě)),這樣就可以在同一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是一樣的,因此稱為是可重復(fù)讀隔離級(jí)別,讀取數(shù)據(jù)的事務(wù)將會(huì)禁止寫(xiě)事務(wù)(但允許讀事務(wù)),寫(xiě)事務(wù)則禁止任何其他事務(wù)(包括了讀寫(xiě)),這樣避免了不可重復(fù)讀和臟讀,但是有時(shí)可能會(huì)出現(xiàn)幻讀
解決了更新丟失、臟讀、不可重復(fù)讀、但是還會(huì)出現(xiàn)幻讀
第四種隔離級(jí)別:Serializable(可序化)
事務(wù)只能一個(gè)接著一個(gè)地執(zhí)行,但不能并發(fā)執(zhí)行。序列化是最高的事務(wù)隔離級(jí)別,同時(shí)代價(jià)也是最高的,性能很低,一般很少使用
解決了更新丟失、臟讀、不可重復(fù)讀、幻讀(虛讀)
MYSQL數(shù)據(jù)庫(kù)中,支持上面四種隔離級(jí)別,默認(rèn)的為Repeatable read(可重復(fù)讀);而在Oracle數(shù)據(jù)庫(kù)中,只支持Serializeble(串行化)級(jí)別和Read committed(讀已提交)這兩種級(jí)別,其中默認(rèn)的為Read committed級(jí)別
5.timeout 屬性timeout :事務(wù)的超時(shí)時(shí)間,默認(rèn)值為 -1。如果超過(guò)該時(shí)間限制但事務(wù)還沒(méi)有完成,則自動(dòng)回滾事務(wù)。
6.readOnly 屬性readOnly :指定事務(wù)是否為只讀事務(wù),默認(rèn)值為 false;為了忽略那些不需要事務(wù)的方法,比如讀取數(shù)據(jù),可以設(shè)置 read-only 為 true。
7.rollbackFor 屬性rollbackFor :用于指定能夠觸發(fā)事務(wù)回滾的異常類型,可以指定多個(gè)異常類型。
8.noRollbackFor屬性**noRollbackFor:拋出指定的異常類型,不回滾事務(wù),也可以指定多個(gè)異常類型。
9.@Transactional失效場(chǎng)景
(1)、@Transactional 應(yīng)用在非 public 修飾的方法上
(2)、@Transactional 注解屬性 propagation 設(shè)置錯(cuò)誤
(3)、@Transactional 注解屬性 rollbackFor 設(shè)置錯(cuò)誤
(4)、同一個(gè)類中方法調(diào)用,導(dǎo)致@Transactional失效
(5)、異常被你的 catch“吃了”導(dǎo)致@Transactional失效
(6)、數(shù)據(jù)庫(kù)引擎不支持事務(wù)