6 個(gè)Spring tx 事務(wù)注解:4種隔離&7種事務(wù)傳播業(yè)務(wù)案例(必須收藏)

image.png

Spring框架的事務(wù)管理模塊叶沛,通過(guò)一系列注解提供了一種強(qiáng)大而靈活的方式來(lái)處理企業(yè)級(jí)Java應(yīng)用程序中的事務(wù)搁痛。@Transactional注解是這一模塊的核心系任,它支持多種事務(wù)屬性哲嘲,如傳播行為峡懈、隔離級(jí)別和超時(shí)設(shè)置说墨,允許開(kāi)發(fā)者以聲明式的方式管理事務(wù)的邊界和特性骏全。此外,@Propagation尼斧、@Isolation@EnableTransactionManagement等注解進(jìn)一步豐富了Spring的事務(wù)管理能力姜贡,使得開(kāi)發(fā)者可以根據(jù)不同的業(yè)務(wù)場(chǎng)景定制事務(wù)策略。這些注解的使用不僅簡(jiǎn)化了事務(wù)代碼的編寫棺棵,還提高了應(yīng)用程序的健壯性和可測(cè)試性楼咳。Spring事務(wù)管理的聲明式特性熄捍,讓開(kāi)發(fā)者能夠?qū)I(yè)務(wù)邏輯與事務(wù)管理邏輯分離,從而創(chuàng)建出更加清晰母怜、可維護(hù)的代碼結(jié)構(gòu)余耽。

肖哥彈架構(gòu) 跟大家“彈彈” 框架注解使用,需要代碼關(guān)注

歷史熱點(diǎn)文章

6個(gè)注解說(shuō)明

@Transactional

1.1 注解作用介紹

@Transactional 注解用于聲明方法或類碟贾,確保它們?cè)谑聞?wù)的上下文中執(zhí)行。這是Spring中處理事務(wù)的最常用方式轨域。
1.2 注解屬性介紹

  • value: 指定事務(wù)管理器的名稱缕陕。
  • timeout: 以秒為單位設(shè)置事務(wù)的超時(shí)時(shí)間。
  • readOnly: 指示事務(wù)是否為只讀事務(wù)疙挺。
  • rollbackFor: 指定導(dǎo)致事務(wù)回滾的異常類數(shù)組。
  • noRollbackFor: 指定即使拋出這些異常也不觸發(fā)事務(wù)回滾的類數(shù)組怜浅。
  • propagation: 指定事務(wù)的傳播行為铐然,默認(rèn)為Propagation.REQUIRED
  • isolation: 指定事務(wù)的隔離級(jí)別恶座,默認(rèn)使用底層數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別搀暑。

1.3 注解業(yè)務(wù)案例

@Transactional(
    value = "customTransactionManager", 
    timeout = 5, 
    readOnly = false, 
    rollbackFor = {IllegalArgumentException.class, CustomException.class}, 
    noRollbackFor = {NoRollbackException.class}, 
    propagation = Propagation.REQUIRED,
    isolation = Isolation.READ_COMMITTED
)
public void updateUserBalance(Long userId, int amount) {
    // 業(yè)務(wù)邏輯,如更新用戶余額
    accountRepository.updateBalance(userId, amount);
    if (accountRepository.getBalance(userId) < 0) {
        throw new CustomException("Insufficient funds");
    }
}

@EnableTransactionManagement

2.1 注解作用介紹

@EnableTransactionManagement 注解用于開(kāi)啟基于注解的事務(wù)管理跨琳,允許在Spring應(yīng)用程序中使用@Transactional注解自点。

2.2 注解屬性介紹

  • 無(wú)特定屬性。

2.3 注解業(yè)務(wù)案例

@Configuration
@EnableTransactionManagement
public class TransactionManagementConfig {
    // 其他配置
}

@TransactionManagementConfigurer

3.1 注解作用介紹

@TransactionManagementConfigurer 注解用于自定義事務(wù)管理器的配置脉让,適用于需要自定義事務(wù)管理器時(shí)桂敛。

3.2 注解屬性介紹

  • 無(wú)特定屬性。

3.3 注解業(yè)務(wù)案例

@Configuration
public class CustomTransactionManagementConfig implements TransactionManagementConfigurer {
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new MyCustomTransactionManager();
    }
}

@Propagation

4.1 注解作用介紹

@Propagation 注解用于指定事務(wù)的傳播行為溅潜,與@Transactional注解的propagation屬性配合使用术唬。

4.2 注解屬性介紹

  • value: 指定事務(wù)的傳播行為,如Propagation.REQUIRED滚澜、Propagation.REQUIRES_NEW等粗仓。

4.3 注解業(yè)務(wù)案例

java
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void someTransactionalMethod() {
    // 業(yè)務(wù)邏輯
}

@Isolation

5.1 注解作用介紹 @Isolation 注解用于設(shè)置事務(wù)的隔離級(jí)別,與@Transactional注解的isolation屬性配合使用设捐。

5.2 注解屬性介紹

  • value: 指定隔離級(jí)別借浊,如Isolation.READ_COMMITTEDIsolation.REPEATABLE_READ等萝招。

5.3 注解業(yè)務(wù)案例

java
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void someTransactionalMethod() {
    // 業(yè)務(wù)邏輯
}

@TransactionAttribute

6.1 注解作用介紹

@TransactionAttribute 注解用于指定事務(wù)的具體屬性蚂斤,如傳播行為和隔離級(jí)別,通常與@Transactional注解配合使用即寒。

6.2 注解屬性介紹

  • value: 指定事務(wù)屬性的組合橡淆。

6.3 注解業(yè)務(wù)案例

@Transactional(
    transactionAttribute = @TransactionAttribute(
        readOnly = true, 
        propagation = Propagation.SUPPORTS
    )
)
public void someTransactionalMethod() {
    // 業(yè)務(wù)邏輯
}

@Propagation召噩、@Isolation@TransactionAttribute注解通常作為@Transactional注解的參數(shù)使用,而不是單獨(dú)使用逸爵。@EnableTransactionManagement@TransactionManagementConfigurer注解用于配置Spring的事務(wù)管理能力具滴。

4種隔離策略案例說(shuō)明

Isolation.DEFAULT

@Transactional(isolation = Isolation.DEFAULT)
public void processUserOrder() {
    // 業(yè)務(wù)邏輯,使用數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別
}
  • 使用條件: 使用數(shù)據(jù)庫(kù)默認(rèn)隔離級(jí)別师倔,適用于大多數(shù)標(biāo)準(zhǔn)業(yè)務(wù)邏輯构韵,不特別指定隔離級(jí)別以利用數(shù)據(jù)庫(kù)的默認(rèn)配置,適合于那些對(duì)隔離級(jí)別沒(méi)有特別要求的場(chǎng)景趋艘。
  • 業(yè)務(wù)案例舉例: 在處理用戶訂單時(shí)疲恢,如果業(yè)務(wù)邏輯不涉及復(fù)雜的并發(fā)操作,使用默認(rèn)隔離級(jí)別可以確保與數(shù)據(jù)庫(kù)配置的一致性瓷胧,同時(shí)簡(jiǎn)化事務(wù)管理显拳。

Isolation.READ_UNCOMMITTED

@Transactional(isolation = Isolation.READ_UNCOMMITTED)
public void generateInventoryReport() {
    // 生成庫(kù)存報(bào)告,允許讀取未提交的數(shù)據(jù)
}
  • 使用條件: 在生成報(bào)告或統(tǒng)計(jì)數(shù)據(jù)時(shí)搓萧,可能不需要完全的數(shù)據(jù)一致性杂数,此時(shí)可以犧牲一點(diǎn)一致性以換取更高的并發(fā)性能,適合于那些對(duì)數(shù)據(jù)實(shí)時(shí)性要求不高的報(bào)告生成場(chǎng)景瘸洛。
  • 業(yè)務(wù)案例舉例: 當(dāng)生成月末庫(kù)存報(bào)告時(shí)揍移,由于報(bào)告的目的是提供概覽信息,而不是用于交易處理反肋,因此可以接受讀取到未提交的事務(wù)數(shù)據(jù)那伐。

Isolation.READ_COMMITTED

@Transactional(isolation = Isolation.READ_COMMITTED)
public void transferFunds(AccountId from, AccountId to, BigDecimal amount) {
    // 資金從一個(gè)賬戶轉(zhuǎn)移到另一個(gè)賬戶
}
  • 使用條件: 保證在事務(wù)中讀取的數(shù)據(jù)是其他事務(wù)已經(jīng)提交的數(shù)據(jù),適用于需要避免讀取到其他未提交事務(wù)影響的數(shù)據(jù)的金融交易場(chǎng)景石蔗。
  • 業(yè)務(wù)案例舉例: 在執(zhí)行銀行賬戶之間的資金轉(zhuǎn)賬時(shí)罕邀,必須確保轉(zhuǎn)賬操作基于已提交的賬戶余額,以防止出現(xiàn)不一致的財(cái)務(wù)記錄养距。

Isolation.REPEATABLE_READ

@Transactional(isolation = Isolation.REPEATABLE_READ)
public void checkAndConfirmBooking(BookingId bookingId) {
    // 檢查預(yù)訂信息并確認(rèn)預(yù)訂
}
  • 使用條件: 在處理過(guò)程中需要多次讀取同一數(shù)據(jù)集燃少,保證這些數(shù)據(jù)在事務(wù)過(guò)程中的一致性,適用于庫(kù)存檢查和訂單處理铃在,確保庫(kù)存數(shù)據(jù)不被其他事務(wù)修改阵具。
  • 業(yè)務(wù)案例舉例: 在旅游預(yù)訂系統(tǒng)中確認(rèn)客戶預(yù)訂時(shí),需要多次檢查房間的可用性定铜,以確保在確認(rèn)過(guò)程中房間不會(huì)被其他客戶預(yù)訂阳液。

Isolation.SERIALIZABLE

@Transactional(isolation = Isolation.SERIALIZABLE)
public void updateCriticalSystemParameters() {
    // 更新關(guān)鍵系統(tǒng)參數(shù)
}
  • 使用條件: 對(duì)于更新關(guān)鍵配置或敏感數(shù)據(jù),需要確保完全的隔離揣炕,避免并發(fā)訪問(wèn)導(dǎo)致的數(shù)據(jù)不一致帘皿,雖然這會(huì)犧牲一定的并發(fā)性能。
  • 業(yè)務(wù)案例舉例: 當(dāng)需要更新影響系統(tǒng)全局運(yùn)行的關(guān)鍵參數(shù)(如交易費(fèi)用率)時(shí)畸陡,使用最高隔離級(jí)別可以確保更新操作的原子性和一致性鹰溜,防止配置錯(cuò)誤虽填。

事務(wù)7種傳播機(jī)制說(shuō)明

Propagation.REQUIRED

  • 案例:

    java
    public class OrderService {
        @Transactional(Propagation.REQUIRED)
        public void processOrder(Order order) {
            // 保存訂單
            saveOrder(order);
            // 扣減庫(kù)存
            reduceInventory(order);
        }
    }
    
  • 使用條件: Propagation.REQUIRED是默認(rèn)設(shè)置,適用于大多數(shù)業(yè)務(wù)邏輯曹动,確保方法在事務(wù)上下文中執(zhí)行斋日,如果當(dāng)前存在事務(wù),則加入該事務(wù)墓陈;如果不存在恶守,則新建一個(gè)。

  • 方法場(chǎng)景: 當(dāng)需要執(zhí)行一系列數(shù)據(jù)庫(kù)操作贡必,這些操作需要作為一個(gè)單一的原子工作單元被提交或回滾兔港,例如處理訂單時(shí)既要保存訂單信息又要扣減庫(kù)存。

Propagation.REQUIRES_NEW

public class UserService {
    @Transactional(Propagation.REQUIRES_NEW)
    public void deleteUser(User user) {
        // 刪除用戶
        userRepository.delete(user);
        // 清除用戶相關(guān)數(shù)據(jù)
        clearUserData(user);
    }
}
  • 使用條件: 當(dāng)需要執(zhí)行一個(gè)新事務(wù)仔拟,并且這個(gè)新事務(wù)必須獨(dú)立于任何現(xiàn)有事務(wù)時(shí)使用衫樊,即使存在一個(gè)活動(dòng)的事務(wù),REQUIRES_NEW也會(huì)創(chuàng)建一個(gè)新的事務(wù)利花。
  • 方法場(chǎng)景: 在刪除用戶時(shí)橡伞,可能需要確保刪除操作在一個(gè)新的事務(wù)中執(zhí)行,以避免由于現(xiàn)有事務(wù)的回滾而影響到刪除操作晋被。

Propagation.SUPPORTS

public class ProductService {
    @Transactional(Propagation.SUPPORTS)
    public List<Product> listProducts() {
        // 返回產(chǎn)品列表
        return productService.findAll();
    }
}
  • 使用條件: 當(dāng)事務(wù)方法被調(diào)用時(shí),如果已經(jīng)存在一個(gè)事務(wù)刚盈,它應(yīng)該在該事務(wù)的上下文中執(zhí)行羡洛;如果沒(méi)有事務(wù)存在,它應(yīng)該非事務(wù)性地執(zhí)行藕漱。
  • 方法場(chǎng)景: 查詢操作欲侮,如列出所有產(chǎn)品的列表,如果存在事務(wù)肋联,則在事務(wù)中執(zhí)行查詢威蕉,否則進(jìn)行普通的查詢。

Propagation.MANDATORY

public class AccountService {
    @Transactional(Propagation.MANDATORY)
    public void transferFunds(Account from, Account to, BigDecimal amount) {
        // 從from賬戶扣款
        from.debit(amount);
        // 給to賬戶加款
        to.credit(amount);
    }
}
  • 使用條件: 事務(wù)方法是在一個(gè)必須存在事務(wù)的上下文中被調(diào)用橄仍,如果不存在事務(wù)韧涨,拋出異常。
  • 方法場(chǎng)景: 執(zhí)行資金轉(zhuǎn)賬時(shí)侮繁,必須確保在事務(wù)的上下文中執(zhí)行虑粥,以保證資金的準(zhǔn)確性和一致性。

Propagation.NESTED

public class TransactionService {
    @Transactional
    public void executeTransactions() {
        // 開(kāi)啟一個(gè)事務(wù)
        performTransaction();
        // 嵌套事務(wù)宪哩,進(jìn)行更細(xì)粒度的操作
        @Transactional(Propagation.NESTED)
        performNestedTransaction();
    }
}
  • 使用條件: 需要在現(xiàn)有的事務(wù)中執(zhí)行一個(gè)或多個(gè)操作娩贷,這些操作需要自己的事務(wù)上下文,例如锁孟,保存點(diǎn)或額外的隔離級(jí)別彬祖。
  • 方法場(chǎng)景: 在執(zhí)行一系列需要額外事務(wù)控制的事務(wù)時(shí)茁瘦,如在主事務(wù)中執(zhí)行額外的事務(wù)以處理更細(xì)粒度的業(yè)務(wù)邏輯。

Propagation.NOT_SUPPORTED

public class CacheService {
    @Transactional(Propagation.NOT_SUPPORTED)
    public void refreshCache() {
        // 刷新緩存储笑,不需要事務(wù)
        cacheManager.clearCache();
    }
}
  • 使用條件: 事務(wù)方法不應(yīng)該運(yùn)行在任何事務(wù)上下文中甜熔,如果存在一個(gè)活動(dòng)的事務(wù),它應(yīng)該被掛起南蓬。
  • 方法場(chǎng)景: 執(zhí)行不需要事務(wù)的操作纺非,如刷新緩存,以避免與可能存在的事務(wù)沖突赘方。

Propagation.NEVER

public class AuditService {
    @Transactional(Propagation.NEVER)
    public void logAuditEvent(AuditEvent event) {
        // 記錄審計(jì)事件烧颖,不允許在事務(wù)上下文中執(zhí)行
        auditRepository.save(event);
    }
}
  • 使用條件: 事務(wù)方法不應(yīng)該運(yùn)行在任何事務(wù)上下文中,如果存在一個(gè)活動(dòng)的事務(wù)窄陡,拋出異常炕淮。
  • 方法場(chǎng)景: 記錄審計(jì)事件時(shí),需要確保這些記錄操作不會(huì)受到任何現(xiàn)有事務(wù)的影響跳夭,以保證審計(jì)數(shù)據(jù)的完整性涂圆。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市币叹,隨后出現(xiàn)的幾起案子润歉,更是在濱河造成了極大的恐慌,老刑警劉巖颈抚,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踩衩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡贩汉,警方通過(guò)查閱死者的電腦和手機(jī)驱富,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)匹舞,“玉大人褐鸥,你說(shuō)我怎么就攤上這事〈突” “怎么了叫榕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)姊舵。 經(jīng)常有香客問(wèn)我翠霍,道長(zhǎng),這世上最難降的妖魔是什么蠢莺? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任寒匙,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘锄弱。我一直安慰自己考蕾,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布会宪。 她就那樣靜靜地躺著肖卧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掸鹅。 梳的紋絲不亂的頭發(fā)上塞帐,一...
    開(kāi)封第一講書(shū)人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音巍沙,去河邊找鬼葵姥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛句携,可吹牛的內(nèi)容都是我干的榔幸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼矮嫉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼削咆!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起蠢笋,我...
    開(kāi)封第一講書(shū)人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拨齐,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后昨寞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體瞻惋,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年编矾,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片馁害。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窄俏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碘菜,到底是詐尸還是另有隱情凹蜈,我是刑警寧澤,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布忍啸,位于F島的核電站仰坦,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏计雌。R本人自食惡果不足惜悄晃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧妈橄,春花似錦庶近、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沙热,卻和暖如春叉钥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背篙贸。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工投队, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人歉秫。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓蛾洛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親雁芙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子轧膘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容