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

