最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何使用Spring boot的@Transactional進行事務管理

 更新時間:2025年02月11日 15:25:52   作者:TracyCoder123  
這篇文章介紹了SpringBoot中使用@Transactional注解進行聲明式事務管理的詳細信息,包括基本用法、核心配置參數(shù)、關鍵注意事項、調(diào)試技巧、最佳實踐以及完整示例,感興趣的朋友一起看看吧

在 Spring Boot 中,@Transactional 是用于聲明式事務管理的關鍵注解。它基于 Spring 的 AOP(面向切面編程)實現(xiàn),可以簡化數(shù)據(jù)庫事務的管理。

一、前置條件

  • 依賴引入:確保項目中包含 spring-boot-starter-data-jpaspring-boot-starter-jdbc
  • 啟用事務管理:Spring Boot 默認自動配置事務管理器(如 DataSourceTransactionManager),無需手動啟用。

二、基本用法

1. 在方法上添加注解

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
        // 其他數(shù)據(jù)庫操作
    }
}

2. 在類上添加注解

@Service
@Transactional
public class UserService {
    // 類中所有 public 方法都會應用事務
}

三、核心配置參數(shù)

1. 傳播行為(Propagation)

控制事務的邊界,默認為 Propagation.REQUIRED

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser(User user) {
    // 始終開啟新事務
}

常見選項:

  • REQUIRED(默認):如果當前存在事務,則加入;否則新建
  • REQUIRES_NEW:始終新建事務,掛起當前事務(如有)
  • SUPPORTS:如果當前存在事務,則加入;否則非事務運行
  • NOT_SUPPORTED:非事務運行,掛起當前事務(如有)
  • MANDATORY:必須在事務中調(diào)用,否則拋出異常
  • NEVER:必須在非事務中調(diào)用,否則拋出異常

2. 隔離級別(Isolation)

控制事務的隔離性,默認為 Isolation.DEFAULT(使用數(shù)據(jù)庫默認)。

@Transactional(isolation = Isolation.SERIALIZABLE)
public void sensitiveOperation() {
    // 最高隔離級別
}

3. 超時時間(Timeout)

事務超時時間(秒),默認-1(使用數(shù)據(jù)庫默認)。

@Transactional(timeout = 30)
public void longRunningProcess() {
    // 超過30秒將回滾
}

4. 只讀模式(readOnly)

優(yōu)化只讀操作,默認為 false

@Transactional(readOnly = true)
public List<User> findAllUsers() {
    return userRepository.findAll();
}

5. 回滾規(guī)則(rollbackFor/noRollbackFor)

指定觸發(fā)回滾的異常類型:

@Transactional(rollbackFor = CustomException.class)
public void process() throws CustomException {
    // 拋出 CustomException 時回滾
}

四、關鍵注意事項

1. 方法可見性

必須為 public:由于 Spring AOP 的實現(xiàn)機制,非 public 方法上的 @Transactional 無效

2. 自調(diào)用問題

同類中的方法互相調(diào)用時,事務不會生效(繞過代理對象)

// 錯誤示例
public void methodA() {
    methodB(); // 事務不生效
}
@Transactional
public void methodB() { ... }

3. 異常處理

  • 默認回滾條件:拋出 RuntimeException 或 Error
  • 檢查型異常(Checked Exception)默認不會觸發(fā)回滾
// 處理檢查型異常
@Transactional(rollbackFor = IOException.class)
public void fileOperation() throws IOException {
    // ...
}

4. 多數(shù)據(jù)源事務

需配置多個事務管理器,并通過 @Transactional(value = "specificTransactionManager") 指定

五、調(diào)試技巧

啟用調(diào)試日志:

logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=DEBUG

檢查代理對象:

System.out.println(userService.getClass().getName());
// 輸出應為代理類:com.sun.proxy.$ProxyXX 或 ...$$EnhancerBySpringCGLIB$$...

六、最佳實踐

  • 服務層使用:在 Service 層而非 Controller 層使用事務
  • 保持短事務:避免在事務中包含遠程調(diào)用、文件IO等耗時操作
  • 精確回滾規(guī)則:明確指定 rollbackFor 而非依賴默認行為
  • 結合 JPA 使用
@Transactional
public void updateUserEmail(Long userId, String email) {
    User user = userRepository.findById(userId).orElseThrow();
    user.setEmail(email); // 自動臟檢查,事務提交時更新
}

七、完整示例

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private InventoryService inventoryService;
    @Transactional(
        propagation = Propagation.REQUIRED,
        isolation = Isolation.READ_COMMITTED,
        timeout = 30,
        rollbackFor = {InsufficientStockException.class, PaymentFailedException.class}
    )
    public void placeOrder(Order order) {
        inventoryService.reduceStock(order.getItems()); // 可能拋出 InsufficientStockException
        orderRepository.save(order);
        processPayment(order); // 可能拋出 PaymentFailedException
    }
    private void processPayment(Order order) {
        // 支付邏輯
    }
}

八、適用于關系型數(shù)據(jù)庫

@Transactional 的使用與數(shù)據(jù)庫層有直接關系,但它的事務管理機制是基于數(shù)據(jù)庫事務的。如果 Service 層方法使用了 Elasticsearch 客戶端讀寫 Elasticsearch,那么 @Transactional 的行為會受到影響。

1.@Transactional 的適用范圍

  • @Transactional 是 Spring 提供的事務管理機制,主要用于管理數(shù)據(jù)庫事務。
  • 它依賴于底層的事務管理器(如 DataSourceTransactionManager),而這些事務管理器通常是與關系型數(shù)據(jù)庫(如 MySQL、PostgreSQL)交互的。

數(shù)據(jù)庫事務@Transactional 可以確保數(shù)據(jù)庫操作的原子性、一致性、隔離性和持久性(ACID)。非數(shù)據(jù)庫操作:對于非數(shù)據(jù)庫操作(如 Elasticsearch、Redis、文件系統(tǒng)等),@Transactional 無法直接管理其事務。

2.Elasticsearch 與 @Transactional 的關系

Elasticsearch 是一個分布式搜索引擎,它本身不支持傳統(tǒng)意義上的事務(ACID)。因此,@Transactional 對 Elasticsearch 的操作沒有直接的事務管理能力。

(1)場景分析

假設我們的 Service 方法同時操作了數(shù)據(jù)庫和 Elasticsearch:

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository; // 數(shù)據(jù)庫操作
    @Autowired
    private ElasticsearchClient elasticsearchClient; // Elasticsearch 操作
    @Transactional
    public void createUser(User user) {
        // 操作數(shù)據(jù)庫
        userRepository.save(user);
        // 操作 Elasticsearch
        IndexRequest request = new IndexRequest("users")
            .id(user.getId().toString())
            .source("name", user.getName(), "email", user.getEmail());
        elasticsearchClient.index(request, RequestOptions.DEFAULT);
    }
}

(2)可能出現(xiàn)的問題

  • 數(shù)據(jù)庫事務回滾,Elasticsearch 操作不回滾:
  • 如果 userRepository.save(user) 成功,但后續(xù) Elasticsearch 操作失敗,數(shù)據(jù)庫事務會回滾(因為 @Transactional 生效),但 Elasticsearch 的數(shù)據(jù)已經(jīng)寫入,無法回滾。
  • 數(shù)據(jù)庫事務提交,Elasticsearch 操作失敗:
  • 如果數(shù)據(jù)庫操作成功,但 Elasticsearch 操作失敗,數(shù)據(jù)庫事務已經(jīng)提交,而 Elasticsearch 數(shù)據(jù)未更新,導致數(shù)據(jù)不一致。

3.如何解決 Elasticsearch 與數(shù)據(jù)庫的事務一致性問題

由于 Elasticsearch 不支持事務,因此需要采用其他機制來保證數(shù)據(jù)一致性。

(1)手動補償機制 在 Elasticsearch 操作失敗時,手動回滾數(shù)據(jù)庫操作。

示例:

@Transactional
public void createUser(User user) {
    try {
        userRepository.save(user); // 數(shù)據(jù)庫操作
        IndexRequest request = new IndexRequest("users")
            .id(user.getId().toString())
            .source("name", user.getName(), "email", user.getEmail());
        elasticsearchClient.index(request, RequestOptions.DEFAULT); // Elasticsearch 操作
    } catch (Exception e) {
        // Elasticsearch 操作失敗,手動回滾數(shù)據(jù)庫
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        throw e;
    }
}

(2)消息隊列(最終一致性)

  • 將 Elasticsearch 操作異步化,通過消息隊列(如 Kafka、RabbitMQ)實現(xiàn)最終一致性。
  • 示例:

    數(shù)據(jù)庫操作完成后,發(fā)送消息到隊列。

    消費者從隊列中讀取消息并更新 Elasticsearch。

(3)兩階段提交(2PC)

  • 使用分布式事務管理器(如 Seata)實現(xiàn)數(shù)據(jù)庫和 Elasticsearch 的分布式事務。
  • 這種方法復雜度較高,通常不推薦用于 Elasticsearch。

(4)本地消息表

  • 在數(shù)據(jù)庫中創(chuàng)建一張消息表,記錄需要同步到 Elasticsearch 的數(shù)據(jù)。
  • 通過定時任務或事件監(jiān)聽器將數(shù)據(jù)同步到 Elasticsearch。

總結

  • @Transactional 只對數(shù)據(jù)庫事務有效:它無法管理 Elasticsearch 等非關系型數(shù)據(jù)存儲的事務。
  • Elasticsearch 操作與數(shù)據(jù)庫事務的一致性:需要通過補償機制、消息隊列等方式實現(xiàn)。
    • 設計建議: 盡量避免在同一個事務中混合數(shù)據(jù)庫和 Elasticsearch 操作。
    • 采用異步化或最終一致性方案來保證數(shù)據(jù)一致性。

如果你有更多具體的業(yè)務場景,可以進一步討論如何設計解決方案!

到此這篇關于使用Spring boot的@Transactional進行事務管理的文章就介紹到這了,更多相關Spring boot @Transactional事務管理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 使用Java發(fā)送郵件到QQ郵箱的完整指南

    使用Java發(fā)送郵件到QQ郵箱的完整指南

    在現(xiàn)代軟件開發(fā)中,郵件發(fā)送功能是一個常見的需求,無論是用戶注冊驗證、密碼重置,還是系統(tǒng)通知,郵件都是一種重要的通信方式,本文將詳細介紹如何使用Java編寫程序,實現(xiàn)發(fā)送郵件到QQ郵箱的功能,需要的朋友可以參考下
    2025-03-03
  • MyBatis-Plus聯(lián)表查詢以及分頁代碼實例

    MyBatis-Plus聯(lián)表查詢以及分頁代碼實例

    在開發(fā)中遇到了一個問題,需要進行聯(lián)表查詢并進行分頁,因為不想自己來寫分頁,所以還是依靠MybatisPlus來實現(xiàn)想要的功能,下面這篇文章主要給大家介紹了關于MyBatis-Plus聯(lián)表查詢以及分頁的相關資料,需要的朋友可以參考下
    2023-06-06
  • SpringCloud的網(wǎng)關Zuul和Gateway詳解

    SpringCloud的網(wǎng)關Zuul和Gateway詳解

    SpringCloudZuul和SpringCloudGateway都是用于構建微服務架構中的API網(wǎng)關的組件,但SpringCloudGateway在性能、功能特性和生態(tài)支持等方面有一些優(yōu)勢,因此推薦使用SpringCloudGateway作為首選
    2025-02-02
  • Hibernate中實現(xiàn)增刪改查的步驟詳解

    Hibernate中實現(xiàn)增刪改查的步驟詳解

    本篇文章主要介紹了Hibernate中實現(xiàn)增刪改查的步驟與方法,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制

    Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制

    本文主要介紹了Java生產(chǎn)者和消費者實現(xiàn)等待喚醒機制,通過synchronized、wait()和notifyAll()實現(xiàn)線程間的安全協(xié)作,具有一定的參考價值,感興趣的可以了解一下
    2025-06-06
  • IDEA?下?Gradle?刪除多余無用依賴的處理方法

    IDEA?下?Gradle?刪除多余無用依賴的處理方法

    這篇文章主要介紹了IDEA下Gradle刪除多余無用依賴,使用該插件可以一定程度上幫助我們刪除無用依賴,但是也可能會多刪除有用的依賴,需要在使用插件自動修復后手動檢測項目,驗證是否會出現(xiàn)問題,避免導致上線發(fā)布錯誤的負優(yōu)化
    2022-03-03
  • 基于selenium 獲取新頁面元素失敗的解決方法

    基于selenium 獲取新頁面元素失敗的解決方法

    今天小編就為大家分享一篇基于selenium 獲取新頁面元素失敗的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • Java中的logback標記日志過濾器MarkerFilter詳解

    Java中的logback標記日志過濾器MarkerFilter詳解

    這篇文章主要介紹了Java中的logback標記日志過濾器MarkerFilter詳解,在logback-classic中存在一個全局過濾器TurboFilter,TurboFilter是與LoggerContext綁定,會在會在其它過濾器之前執(zhí)行,需要的朋友可以參考下
    2023-11-11
  • Java實例講解反射機制是怎么一回事

    Java實例講解反射機制是怎么一回事

    Java的反射(reflection)機制是指在程序的運行狀態(tài)中,可以構造任意一個類的對象,可以了解任意一個對象所屬的類,可以了解任意一個類的成員變量和方法,可以調(diào)用任意一個對象的屬性和方法
    2022-03-03
  • Java?Jenkins、Dockers和Kubernetes有什么區(qū)別詳細總結

    Java?Jenkins、Dockers和Kubernetes有什么區(qū)別詳細總結

    這篇文章主要介紹了Java?Jenkins、Dockers和Kubernetes有什么區(qū)別的相關資料,Jenkins、Docker和Kubernetes分別在自動化流程、容器化封裝與容器編排三個關鍵層面發(fā)揮著重要作用,需要的朋友可以參考下
    2025-11-11

最新評論

任丘市| 马尔康县| 阳信县| 泸溪县| 新巴尔虎左旗| 江华| 舞阳县| 连山| 辉南县| 铜鼓县| 海宁市| 类乌齐县| 桃园县| 惠安县| 界首市| 龙川县| 黑龙江省| 信丰县| 都安| 保康县| 新乐市| 德江县| 安图县| 东海县| 安义县| 哈尔滨市| 北宁市| 舞钢市| 达日县| 大厂| 桃园县| 叶城县| 景泰县| 石阡县| 秦安县| 弥勒县| 婺源县| 蓝田县| 镇赉县| 郁南县| 双鸭山市|