Spring的事務(wù)管理
1、事務(wù)的回顧
【1】事務(wù)的定義
是數(shù)據(jù)庫(kù)操作的最小工作單元,是作為單個(gè)邏輯工作單元執(zhí)行的一系列操作,這些操作作為一個(gè)整體一起向系統(tǒng)提交,要么都執(zhí)行、要么都不執(zhí)行;事務(wù)是一組不可再分割的操作集合
【2】事務(wù)的ACID原則
事務(wù)具有4個(gè)基本特性:原子性、一致性、隔離性、持久性。也就是我們常說(shuō)的ACID原則
-
原子性(Atomicity):
一個(gè)事務(wù)已經(jīng)是一個(gè)不可再分割的工作單位。事務(wù)中的全部操作要么都做;要么都不做例如:A和B兩個(gè)人一共1000元,A給B轉(zhuǎn)賬100元,A付款100元,B收款100元, A的付款行為和B的收款行為要么都成功,要么都失敗
-
一致性(Consistency):
事務(wù)的執(zhí)行使數(shù)據(jù)從一個(gè)狀態(tài)轉(zhuǎn)換為另一個(gè)狀態(tài),但是對(duì)于整個(gè)數(shù)據(jù)的完整性保持穩(wěn)定。例如:A和B兩個(gè)人一共1000元,無(wú)論A,B兩人互相轉(zhuǎn)賬多少次,A和B兩個(gè)人總額都應(yīng)該是1000元
-
隔離性(Isolation):
事務(wù)允許多個(gè)用戶對(duì)同一個(gè)數(shù)據(jù)進(jìn)行并發(fā)訪問(wèn),而不破壞數(shù)據(jù)的正確性 和完整性。同時(shí),并行事務(wù)的修改必須與其他并行事務(wù)的修改相互獨(dú)立。
例如:萬(wàn)達(dá)影院有《葉問(wèn)4》電影票100張,允許所有人同時(shí)去淘票票上購(gòu)票,當(dāng)?shù)?00張電影票被A,B,C3人同時(shí)購(gòu)買,如果A拿到第100張電影票,但是還在猶豫要不要付錢,則B,C必須等待A的決定,如果A決定付錢,B.C就無(wú)法搶到票,如果A超時(shí)不付錢,則這第100張電影票回歸票池,從新分配。
-
持久性(Durability):
一個(gè)事務(wù)一旦提交,它對(duì)數(shù)據(jù)庫(kù)中數(shù)據(jù)的改變會(huì)永久存儲(chǔ)起來(lái)。其他操作不會(huì)對(duì)它產(chǎn)生影響例如:萬(wàn)達(dá)影院有《葉問(wèn)4》電影票100張,100張電影票銷售完畢,對(duì)于每個(gè)購(gòu)買者來(lái)說(shuō),他的購(gòu)買記錄已經(jīng)產(chǎn)生,即使退票,他之前的購(gòu)買記錄也不會(huì)消失。
2、spring事務(wù)API介紹【了解】
【1】PlatformTransactionManager
【1.1】PlatformTransactionManager作用
? PlatformTransactionManager【事務(wù)平臺(tái)管理器】:是一個(gè)接口,定義了獲取事務(wù)、提交事務(wù)、回滾事務(wù)的接口
【1.2】PlatformTransactionManager接口
public interface PlatformTransactionManager {
//根據(jù)事務(wù)定義TransactionDefinition,獲取事務(wù)
TransactionStatus getTransaction(TransactionDefinition definition);
//提交事務(wù)
void commit(TransactionStatus status);
//回滾事務(wù)
void rollback(TransactionStatus status);
}
【1.3】PlatformTransactionManager實(shí)現(xiàn)類
事務(wù)平臺(tái)管理器PlatformTransactionManager定義了標(biāo)準(zhǔn),他有如下經(jīng)常使用的實(shí)現(xiàn)
PlatformTransactionManager的實(shí)現(xiàn)類 | 說(shuō)明 |
---|---|
org.springframework.jdbc.datasource.DataSourceTransactionManager | DataSource 數(shù)據(jù)源的事務(wù) |
org.springframework.orm.hibernateX.HibernateTransactionManager | Hibernate 事務(wù)管理器。 |
org.springframework.orm.jpa.JpaTransactionManager | JPA 事務(wù)管理器 |
org.springframework.transaction.jta.JtaTransactionManager | 多個(gè)數(shù)據(jù)源的全局事務(wù)管理器 |
org.springframework.orm.jdo.JdoTransactionManager | JDO 事務(wù)管理器 |
【2】TransactionDefinition
【2.1】TransactionDefinition作用
TransactionDefinition【事務(wù)定義信息】:是一個(gè)接口,定義了事務(wù)隔離級(jí)別、事務(wù)傳播行為、事務(wù)超時(shí)時(shí)間、事務(wù)是否只讀
【2.2】TransactionDefinition接口
public interface TransactionDefinition {
/**********************事務(wù)傳播行為類型常量***********************************/
//事務(wù)傳播行為類型:如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。
int PROPAGATION_REQUIRED = 0;
//事務(wù)傳播行為類型:支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。
int PROPAGATION_SUPPORTS = 1;
//事務(wù)傳播行為類型:當(dāng)前如果有事務(wù),Spring就會(huì)使用該事務(wù);否則會(huì)拋出異常
int PROPAGATION_MANDATORY = 2;
//事務(wù)傳播行為類型:新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
int PROPAGATION_REQUIRES_NEW = 3;
//事務(wù)傳播行為類型:以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
int PROPAGATION_NOT_SUPPORTED = 4;
//事務(wù)傳播行為類型:即使當(dāng)前有事務(wù),Spring也會(huì)在非事務(wù)環(huán)境下執(zhí)行。如果當(dāng)前有事務(wù),則拋出異常
int PROPAGATION_NEVER = 5;
//事務(wù)傳播行為類型:如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。
int PROPAGATION_NESTED = 6;
/**********************事務(wù)隔離級(jí)別常量***********************************/
//MySQL默認(rèn)采用ISOLATION_REPEATABLE_READ,Oracle采用READ__COMMITTED級(jí)別。)
//隔離級(jí)別:默認(rèn)的隔離級(jí)別()
int ISOLATION_DEFAULT = -1;
//隔離級(jí)別:讀未提交(最低)
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
//隔離級(jí)別:讀提交
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
//隔離級(jí)別:可重復(fù)度
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
//隔離級(jí)別:序列化操作(最高)
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
//默認(rèn)事務(wù)的超時(shí)時(shí)間
int TIMEOUT_DEFAULT = -1;
//獲取事務(wù)的傳播行為
int getPropagationBehavior();
//獲取事務(wù)的隔離級(jí)別
int getIsolationLevel();
//獲取超時(shí)時(shí)間
int getTimeout();
//是否只讀
boolean isReadOnly();
//事務(wù)名稱
String getName();
}
【2.3】事務(wù)隔離級(jí)別
【2.3.1】為什么要事務(wù)隔離?
如果沒(méi)有定義事務(wù)隔離級(jí)別:
- 臟讀 :
? 在一個(gè)事務(wù)中讀取到了另外一個(gè)事務(wù)修改的【未提交的數(shù)據(jù)】,而導(dǎo)致多次讀取同一個(gè)數(shù)據(jù)返回的結(jié)果不一致 (必須要解決的)
例如:
1.事務(wù)1,小明的原工資為1000, 財(cái)務(wù)人員將小明的工資改為了8000【但未提交事務(wù)】
2.事務(wù)2,小明讀取自己的工資 ,發(fā)現(xiàn)自己的工資變?yōu)榱?000,歡天喜地!
3.事務(wù)1,財(cái)務(wù)發(fā)現(xiàn)操作有誤,回滾了操作,小明的工資又變?yōu)榱?000
像這樣,小明讀取的工資數(shù)8000是一個(gè)臟數(shù)據(jù)
- 不可重復(fù)讀 :
? 在一個(gè)事務(wù)中讀取到了另外一個(gè)事務(wù)修改的【已提交的數(shù)據(jù)】,而導(dǎo)致多次讀取同一個(gè)數(shù)據(jù)返回的結(jié)果不一致
例如:
1.事務(wù)1,小明讀取了自己的工資為1000,操作還沒(méi)有完成
2.事務(wù)2,這時(shí)財(cái)務(wù)人員修改了小明的工資為2000,并提交了事務(wù).
3.事務(wù)1,小明再次讀取自己的工資時(shí),工資變?yōu)榱?000
-
幻讀(虛讀):
? 一個(gè)事務(wù)讀取了幾行記錄后,另一個(gè)事務(wù)插入一些記錄,幻讀就發(fā)生了。再后來(lái)的查詢中,第一個(gè)事務(wù)就會(huì)發(fā)現(xiàn)有些原來(lái)沒(méi)有的記錄
例如:
1.事務(wù)1,財(cái)務(wù)統(tǒng)計(jì)所有工資為5000的員工有10人。
2.事務(wù)2,人事向user表插入了一條員工記錄,工資也為5000
3.事務(wù)1,財(cái)務(wù)再次讀取所有工資為5000的員工 共讀取到了11條記錄,明明剛剛是10人???產(chǎn)生幻覺(jué)了?
事務(wù)隔離就是幫助我們解決:臟讀、不可重復(fù)讀、幻讀(虛讀)
【2.3.2】spring事務(wù)隔離級(jí)別
隔離級(jí)別由低到高【讀未提交】=>【讀已提交】=>【可重復(fù)讀】=>【序列化操作】
隔離級(jí)別 | 說(shuō)明 | 臟讀 | 不可重復(fù)讀 | 幻讀 |
---|---|---|---|---|
ISOLATION_DEFAULT | spring默認(rèn)數(shù)據(jù)庫(kù)的隔離級(jí)別 | – | – | – |
ISOLATION_READ_UNCOMMITTED | 讀未提交 | √ | √ | √ |
ISOLATION_READ_COMMITTED | 讀已提交 | × | √ | √ |
ISOLATION_REPEATABLE_READ | 可重復(fù)讀 | × | × | √ |
ISOLATION_SERIALIZABLE | 序列化操作 | × | × | × |
對(duì)大多數(shù)數(shù)據(jù)庫(kù)來(lái)說(shuō)就是:READ_COMMITTED
(讀已提交)
MySQL默認(rèn)采用:REPEATABLE_READ
(可重復(fù)讀),
Oracle采用READ__COMMITTED()
Spring
的隔離級(jí)別默認(rèn)數(shù)據(jù)庫(kù)的隔離級(jí)別:ISOLATION_DEFAULT
【2.4】事務(wù)傳播行為
事務(wù)傳播行為:指的就是當(dāng)一個(gè)事務(wù)方法被另一個(gè)事務(wù)方法調(diào)用時(shí),這個(gè)事務(wù)方法應(yīng)該如何進(jìn)行。
傳播行為 | 說(shuō)明 |
---|---|
REQUIRED | 當(dāng)前如果有事務(wù),Spring就會(huì)使用該事務(wù);否則會(huì)開(kāi)始一個(gè)新事務(wù)(增、刪、改) |
SUPPORTS | 當(dāng)前如果有事務(wù),Spring就會(huì)使用該事務(wù);否則不會(huì)開(kāi)始一個(gè)新事務(wù)(查詢) |
MANDATORY | 當(dāng)前如果有事務(wù),Spring就會(huì)使用該事務(wù);否則會(huì)拋出異常 |
REQUIRES_NEW | 當(dāng)前如果有事務(wù),把當(dāng)前事務(wù)掛起,新建事務(wù) |
NOT_SUPPORTED | 當(dāng)前有事務(wù),Spring也會(huì)在非事務(wù)環(huán)境下執(zhí)行。如果當(dāng)前有事務(wù),則該事務(wù)掛起 |
NEVER | 當(dāng)前有事務(wù),Spring也會(huì)在非事務(wù)環(huán)境下執(zhí)行。如果當(dāng)前有事務(wù),則拋出異常 |
NESTED | 當(dāng)前有事務(wù),則在嵌套事務(wù)中執(zhí)行。如果沒(méi)有,那么執(zhí)行情況與REQUIRED一樣 |
【默認(rèn)】REQUIRED:當(dāng)前如果有事務(wù),Spring就會(huì)使用該事務(wù);否則會(huì)開(kāi)始一個(gè)新事務(wù)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-414672.html
3、擴(kuò)展鏈接
事務(wù)隔離級(jí)別中的可重復(fù)讀能防幻讀嗎?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-414672.html
到了這里,關(guān)于Spring的事務(wù)管理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!