SpringBoot 編程式事務(wù)使用及兩種實(shí)現(xiàn)方式
1. 簡介
編程式事務(wù)管理是通過編寫代碼來管理事務(wù),相對于聲明式事務(wù)(@Transactional注解),它提供了更細(xì)粒度的事務(wù)控制。在 SpringBoot 中,主要有兩種實(shí)現(xiàn)方式:
- 使用 TransactionTemplate
- 直接使用 TransactionManager
2. TransactionTemplate 方式
TransactionTemplate 是最簡單的編程式事務(wù)實(shí)現(xiàn)方式,它對底層事務(wù) API 進(jìn)行了封裝,使用起來更加便捷。
2.1 基本配置
@Configuration public class TransactionConfig { @Autowired private PlatformTransactionManager transactionManager; @Bean public TransactionTemplate transactionTemplate() { TransactionTemplate template = new TransactionTemplate(); template.setTransactionManager(transactionManager); // 設(shè)置默認(rèn)的事務(wù)傳播行為 template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // 設(shè)置默認(rèn)的事務(wù)隔離級別 template.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT); // 設(shè)置默認(rèn)超時時間 template.setTimeout(30); return template; } }
2.2 基本使用示例
@Service @Slf4j public class UserService { @Autowired private TransactionTemplate transactionTemplate; @Autowired private UserRepository userRepository; public User createUser(User user) { // 使用 execute 方法執(zhí)行有返回值的事務(wù)操作 return transactionTemplate.execute(status -> { try { User savedUser = userRepository.save(user); // 模擬其他操作 updateUserProfile(savedUser); return savedUser; } catch (Exception e) { // 手動標(biāo)記事務(wù)回滾 status.setRollbackOnly(); log.error("創(chuàng)建用戶失敗", e); throw new RuntimeException("創(chuàng)建用戶失敗", e); } }); } public void batchCreateUsers(List<User> users) { // 使用 executeWithoutResult 方法執(zhí)行無返回值的事務(wù)操作 transactionTemplate.executeWithoutResult(status -> { try { for (User user : users) { userRepository.save(user); } } catch (Exception e) { status.setRollbackOnly(); log.error("批量創(chuàng)建用戶失敗", e); throw new RuntimeException("批量創(chuàng)建用戶失敗", e); } }); } }
3. TransactionManager 方式
直接使用 TransactionManager 提供了更細(xì)粒度的事務(wù)控制,但使用起來相對復(fù)雜。
3.1 基本使用示例
@Service @Slf4j public class OrderService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private OrderRepository orderRepository; public Order createOrder(Order order) { // 定義事務(wù)屬性 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); def.setTimeout(30); // 獲取事務(wù)狀態(tài) TransactionStatus status = transactionManager.getTransaction(def); try { // 執(zhí)行業(yè)務(wù)邏輯 Order savedOrder = orderRepository.save(order); // 處理訂單相關(guān)的其他操作 processOrderDetails(savedOrder); // 提交事務(wù) transactionManager.commit(status); return savedOrder; } catch (Exception e) { // 回滾事務(wù) transactionManager.rollback(status); log.error("創(chuàng)建訂單失敗", e); throw new RuntimeException("創(chuàng)建訂單失敗", e); } } }
3.2 嵌套事務(wù)示例
@Service @Slf4j public class PaymentService { @Autowired private PlatformTransactionManager transactionManager; @Autowired private PaymentRepository paymentRepository; public void processPayment(Payment payment) { // 外部事務(wù)定義 DefaultTransactionDefinition outerDef = new DefaultTransactionDefinition(); outerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus outerStatus = transactionManager.getTransaction(outerDef); try { // 外部事務(wù)操作 paymentRepository.save(payment); // 內(nèi)部事務(wù)定義 DefaultTransactionDefinition innerDef = new DefaultTransactionDefinition(); innerDef.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); TransactionStatus innerStatus = transactionManager.getTransaction(innerDef); try { // 執(zhí)行內(nèi)部事務(wù)操作 processPaymentDetails(payment); transactionManager.commit(innerStatus); } catch (Exception e) { // 回滾內(nèi)部事務(wù) transactionManager.rollback(innerStatus); log.error("支付詳情處理失敗", e); throw e; } // 提交外部事務(wù) transactionManager.commit(outerStatus); } catch (Exception e) { // 回滾外部事務(wù) transactionManager.rollback(outerStatus); log.error("支付處理失敗", e); throw new RuntimeException("支付處理失敗", e); } } }
4. 事務(wù)傳播行為
在編程式事務(wù)中,我們可以精確控制事務(wù)的傳播行為:
@Service public class TransactionPropagationExample { @Autowired private TransactionTemplate transactionTemplate; public void demonstratePropagation() { // REQUIRED 傳播行為 TransactionTemplate requiredTemplate = new TransactionTemplate(transactionTemplate); requiredTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); // REQUIRES_NEW 傳播行為 TransactionTemplate requiresNewTemplate = new TransactionTemplate(transactionTemplate); requiresNewTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 嵌套使用不同的傳播行為 requiredTemplate.execute(outerStatus -> { // 外部事務(wù)邏輯 requiresNewTemplate.execute(innerStatus -> { // 內(nèi)部事務(wù)邏輯(新的事務(wù)) return null; }); return null; }); } }
5. 事務(wù)隔離級別
示例展示如何設(shè)置不同的事務(wù)隔離級別:
@Service public class TransactionIsolationExample { @Autowired private PlatformTransactionManager transactionManager; public void demonstrateIsolation() { // 讀已提交隔離級別 DefaultTransactionDefinition readCommittedDef = new DefaultTransactionDefinition(); readCommittedDef.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); TransactionStatus readCommittedStatus = transactionManager.getTransaction(readCommittedDef); try { // 業(yè)務(wù)邏輯 transactionManager.commit(readCommittedStatus); } catch (Exception e) { transactionManager.rollback(readCommittedStatus); throw e; } // 可重復(fù)讀隔離級別 DefaultTransactionDefinition repeatableReadDef = new DefaultTransactionDefinition(); repeatableReadDef.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ); // ... 類似的事務(wù)處理邏輯 } }
6. 最佳實(shí)踐
6.1 事務(wù)模板封裝
創(chuàng)建一個通用的事務(wù)處理模板:
@Component @Slf4j public class TransactionHelper { @Autowired private TransactionTemplate transactionTemplate; public <T> T executeInTransaction(TransactionCallback<T> action) { try { return transactionTemplate.execute(action); } catch (Exception e) { log.error("事務(wù)執(zhí)行失敗", e); throw new RuntimeException("事務(wù)執(zhí)行失敗", e); } } public void executeInTransactionWithoutResult(Consumer<TransactionStatus> action) { try { transactionTemplate.executeWithoutResult(action); } catch (Exception e) { log.error("事務(wù)執(zhí)行失敗", e); throw new RuntimeException("事務(wù)執(zhí)行失敗", e); } } } // 使用示例 @Service public class BusinessService { @Autowired private TransactionHelper transactionHelper; public void doBusiness() { transactionHelper.executeInTransactionWithoutResult(status -> { // 業(yè)務(wù)邏輯 }); } }
7. 常見問題與解決方案
7.1 事務(wù)超時處理
@Service public class TimeoutExample { @Autowired private TransactionTemplate transactionTemplate; public void handleTimeout() { TransactionTemplate timeoutTemplate = new TransactionTemplate(transactionTemplate); timeoutTemplate.setTimeout(5); // 設(shè)置5秒超時 try { timeoutTemplate.execute(status -> { // 可能超時的業(yè)務(wù)邏輯 return null; }); } catch (TransactionTimedOutException e) { // 處理超時異常 log.error("事務(wù)執(zhí)行超時", e); throw new RuntimeException("事務(wù)執(zhí)行超時", e); } } }
7.2 異常處理最佳實(shí)踐
@Service public class ExceptionHandlingExample { @Autowired private TransactionTemplate transactionTemplate; public void handleExceptions() { try { transactionTemplate.execute(status -> { try { // 業(yè)務(wù)邏輯 return null; } catch (BusinessException e) { // 業(yè)務(wù)異常,標(biāo)記回滾 status.setRollbackOnly(); throw e; } catch (Exception e) { // 其他異常,標(biāo)記回滾 status.setRollbackOnly(); throw new RuntimeException("未預(yù)期的錯誤", e); } }); } catch (Exception e) { // 統(tǒng)一異常處理 handleException(e); } } private void handleException(Exception e) { if (e instanceof BusinessException) { // 處理業(yè)務(wù)異常 log.warn("業(yè)務(wù)異常: {}", e.getMessage()); } else { // 處理系統(tǒng)異常 log.error("系統(tǒng)異常", e); } throw e; } }
雖然編程式事務(wù)提供了更細(xì)粒度的控制,但在大多數(shù)情況下,聲明式事務(wù)(@Transactional)可能是更好的選擇。只有在需要特別精細(xì)的事務(wù)控制時,才考慮使用編程式事務(wù)。
到此這篇關(guān)于SpringBoot 編程式事務(wù)使用的文章就介紹到這了,更多相關(guān)SpringBoot 編程式事務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot jasypt2.x與jasypt3.x的使用方式
在軟件開發(fā)中,將配置文件中的敏感信息(如數(shù)據(jù)庫密碼)進(jìn)行加密是保障安全的有效手段,jasypt框架提供了這一功能,支持通過加密工具類或命令行工具生成密文,并通過修改配置文件和啟動參數(shù)的方式使用密文和密鑰,這樣即便配置文件被泄露2024-09-09jstl之map,list訪問遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)
下面小編就為大家?guī)硪黄猨stl之map,list訪問遍歷以及el表達(dá)式map取值的實(shí)現(xiàn)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03IntelliJ?IDEA?2023.1.4?無法刷新Maven項(xiàng)目模塊的問題及解決方法
這篇文章主要介紹了如何排查?IDEA?自身報(bào)錯問題,本文以IntelliJ?IDEA?2023.1.4無法刷新項(xiàng)目Maven模塊的問題為例,給大家詳細(xì)講解,需要的朋友可以參考下2023-08-08解決SpringCloud下spring-boot-maven-plugin插件的打包問題
這篇文章主要介紹了SpringCloud下spring-boot-maven-plugin插件的打包問題,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-03-03詳解springboot+mybatis-plue實(shí)現(xiàn)內(nèi)置的CRUD使用詳情
這篇文章主要介紹了詳解springboot+mybatis-plue實(shí)現(xiàn)內(nèi)置的CRUD使用詳情,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07Java中final關(guān)鍵字和final的4種用法
這篇文章主要給大家分享的是?Java中final關(guān)鍵字和final的4種用法修飾類、修飾方法、修飾變量、修飾參數(shù),下面文章具有一定的參考價值,需要的小伙伴可以參考一下2021-11-11Flutter 通過Clipper實(shí)現(xiàn)各種自定義形狀的示例代碼
這篇文章主要介紹了Flutter 通過Clipper實(shí)現(xiàn)各種自定義形狀的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Java內(nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因與解決方案詳解
這篇文章主要為大家詳細(xì)介紹了Java因?yàn)閮?nèi)部類持有外部類導(dǎo)致內(nèi)存泄露的原因以及其解決方案,文中的示例代碼講解詳細(xì),希望對大家有所幫助2022-11-11