亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring?Boot?中事務的用法示例詳解

 更新時間:2025年02月24日 10:26:51   作者:大溪地C  
本文詳細介紹了Spring Boot中事務管理的使用方法,包括事務的基本概念、配置、傳播行為、隔離級別以及回滾機制,通過使用@Transactional注解,可以方便地實現(xiàn)事務的控制,文章還討論了事務方法的可見性、自我調用問題以及超時設置等注意事項,感興趣的朋友一起看看吧

引言 

在 Spring Boot 中,事務管理是一個非常重要的功能,尤其是在涉及數(shù)據(jù)庫操作的業(yè)務場景中。Spring 提供了強大的事務管理支持,能夠幫助我們簡化事務的管理和控制。本文將詳細介紹 Spring Boot 中事務的用法,包括事務的基本概念、事務的配置、事務的傳播行為、事務的隔離級別以及事務的回滾機制。

1. 事務的基本概念

事務(Transaction)是指一組數(shù)據(jù)庫操作,這些操作要么全部成功,要么全部失敗。事務的四大特性(ACID)包括:

  • 原子性(Atomicity):事務中的所有操作要么全部成功,要么全部失敗。
  • 一致性(Consistency):事務執(zhí)行前后,數(shù)據(jù)庫的狀態(tài)保持一致。
  • 隔離性(Isolation):多個事務并發(fā)執(zhí)行時,彼此之間互不干擾。
  • 持久性(Durability):事務一旦提交,對數(shù)據(jù)庫的修改是永久性的。

在 Spring Boot 中,事務管理是通過 @Transactional 注解來實現(xiàn)的。

2. Spring Boot 中事務的配置

2.1 啟用事務管理

Spring Boot 默認已經集成了事務管理功能,只需要在配置類或啟動類上添加 @EnableTransactionManagement 注解即可啟用事務管理。

@SpringBootApplication
@EnableTransactionManagement // 啟用事務管理
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

2.2 配置數(shù)據(jù)源和事務管理器

Spring Boot 默認使用 DataSourceTransactionManager 作為事務管理器。如果你使用的是 Spring Data JPA,事務管理器會自動配置。

# application.yml
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver

3. 使用 @Transactional 注解

@Transactional 是 Spring 提供的事務管理注解,可以標注在類或方法上。標注在類上時,表示該類中的所有方法都啟用事務管理;標注在方法上時,表示該方法啟用事務管理。

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    @Transactional // 開啟事務  表示該方法開啟了事務
    public void createUser(User user) {
        userRepository.save(user);
    }
}

3.2 事務的傳播行為

事務的傳播行為(Propagation)定義了事務方法之間的調用關系。Spring 提供了以下幾種傳播行為:

  • REQUIRED(默認):如果當前存在事務,則加入該事務;如果當前沒有事務,則創(chuàng)建一個新的事務。(適用于大多數(shù)業(yè)務場景,尤其是需要保證多個操作在同一個事務中執(zhí)行的場景。 例如,訂單創(chuàng)建時需要同時更新訂單表和庫存表。)
  • REQUIRES_NEW:無論當前是否存在事務,都創(chuàng)建一個新的事務。(適用于需要獨立事務的場景,尤其是日志記錄、審計等操作。 例如,記錄操作日志時,即使主事務失敗,日志記錄仍然需要成功。)
  • SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務方式執(zhí)行。(適用于不需要強制事務的場景,例如查詢操作。 例如,查詢用戶信息時,如果調用方有事務,則加入事務;如果沒有事務,則以非事務方式執(zhí)行。)
  • NOT_SUPPORTED:以非事務方式執(zhí)行操作,如果當前存在事務,則掛起該事務。(適用于不需要事務支持的場景,例如發(fā)送消息、調用外部接口等。 例如,發(fā)送短信通知時,不需要事務支持。)
  • MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出異常。(適用于強制要求調用方必須有事務的場景。 例如,某些核心業(yè)務邏輯必須在一個事務中執(zhí)行。)
  • NEVER:以非事務方式執(zhí)行操作,如果當前存在事務,則拋出異常。(適用于強制要求調用方不能有事務的場景。 例如,某些只讀操作或外部調用。)
  • NESTED:如果當前存在事務,則在嵌套事務內執(zhí)行;如果當前沒有事務,則創(chuàng)建一個新的事務。(適用于需要部分回滾的場景。 例如,訂單創(chuàng)建時需要更新多個表,如果某個表更新失敗,只需要回滾該表的操作,而不影響其他表的操作。)

示例:

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void updateUser(User user) {
    userRepository.save(user);
}

3.3 事務的隔離級別

事務的隔離級別(Isolation)定義了事務之間的可見性。Spring 支持以下幾種隔離級別:

  • DEFAULT:使用數(shù)據(jù)庫的默認隔離級別。(適用于大多數(shù)通用場景,尤其是當你對數(shù)據(jù)庫的默認行為沒有特殊要求時。 如果你不確定應該選擇哪種隔離級別,可以使用 DEFAULT,讓數(shù)據(jù)庫根據(jù)其默認行為處理事務。)
  • READ_UNCOMMITTED:允許讀取未提交的數(shù)據(jù)變更,可能會導致臟讀、幻讀和不可重復讀。(適用于對數(shù)據(jù)一致性要求不高的場景,例如統(tǒng)計數(shù)據(jù)的讀取或日志記錄。 不適用于涉及資金、訂單等對數(shù)據(jù)一致性要求高的場景。)
  • READ_COMMITTED:只能讀取已提交的數(shù)據(jù),可以避免臟讀,但可能會導致幻讀和不可重復讀。(適用于大多數(shù)業(yè)務場景,尤其是對數(shù)據(jù)一致性有一定要求但不需要嚴格隔離的場景。 例如,電商系統(tǒng)中的訂單查詢、用戶信息查詢等。)
  • REPEATABLE_READ:確保在同一事務中多次讀取同一數(shù)據(jù)時結果一致,可以避免臟讀和不可重復讀,但可能會導致幻讀。(適用于對數(shù)據(jù)一致性要求較高的場景,例如銀行系統(tǒng)中的賬戶余額查詢。 例如,在一個事務中多次讀取同一賬戶的余額時,確保結果一致。)
  • SERIALIZABLE:最高隔離級別,確保事務串行執(zhí)行,可以避免臟讀、幻讀和不可重復讀(適用于對數(shù)據(jù)一致性要求極高的場景,例如金融系統(tǒng)中的資金清算、庫存管理等。 由于性能開銷較大,通常只在必要時使用。)

示例:

@Transactional(isolation = Isolation.READ_COMMITTED)
public User getUserById(Long id) {
    return userRepository.findById(id).orElse(null);
}

3.4 事務的回滾機制

默認情況下,Spring 會在方法拋出 RuntimeException 或 Error 時回滾事務。如果需要自定義回滾規(guī)則,可以通過 rollbackFor(哪些異常回滾) 和 noRollbackFor(哪些異常不會回滾) 屬性來指定。

示例:

@Transactional(rollbackFor = Exception.class) // 所有異常都回滾
public void updateUser(User user) throws Exception {
    userRepository.save(user);
    if (user.getName() == null) {
        throw new Exception("用戶名不能為空"); // 拋出受檢異常
    }
}

4. 事務的嵌套與傳播行為

在復雜的業(yè)務場景中,可能會存在事務方法調用事務方法的情況。此時,事務的傳播行為決定了事務的嵌套方式。

4.1 嵌套事務示例

@Service
public class OrderService {
    @Autowired
    private UserService userService;
    @Transactional  //一級事務
    public void createOrder(Order order) {
        // 保存訂單
        orderRepository.save(order);
        // 調用另一個事務方法
        userService.updateUser(order.getUser());
    }
}
@Service
public class UserService {
    @Transactional(propagation = Propagation.REQUIRES_NEW) //二級事務
    public void updateUser(User user) {
        userRepository.save(user);
    }
}

在上面的示例中,createOrder 方法調用 updateUser 方法時,updateUser 方法會開啟一個新的事務。

5. 事務的注意事項(事務不生效的幾種情況)

事務方法的可見性

@Transactional 只能應用于 public 方法。如果應用于 private 或 protected 方法,事務將不會生效。Spring 的事務管理是基于代理模式實現(xiàn)的,代理對象只能攔截 public 方法。對于 private 或 protected 方法,Spring 無法生成代理,因此事務不會生效。

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;
    // 正確:public 方法,事務生效
    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
    }
    // 錯誤:private 方法,事務不會生效
    @Transactional
    private void updateUser(User user) {
        userRepository.save(user);
    }
    // 錯誤:protected 方法,事務不會生效
    @Transactional
    protected void deleteUser(Long userId) {
        userRepository.deleteById(userId);
    }
}

事務的自我調用問題

如果事務方法調用了同一個類中的另一個事務方法,事務的傳播行為可能不會生效。這是因為Spring 的代理對象只能攔截從外部調用的方法。如果事務方法在同一個類中調用另一個事務方法,實際上是直接調用目標方法,而不是通過代理對象調用,因此事務的傳播行為不會生效。

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Transactional
    public void createOrder(Order order) {
        // 保存訂單
        orderRepository.save(order);
        // 調用另一個事務方法(自我調用)
        updateInventory(order.getProductId(), order.getQuantity());
    }
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateInventory(Long productId, int quantity) {
        // 更新庫存邏輯
    }
}

在上面的示例中,createOrder 方法調用了 updateInventory 方法,但由于是自我調用,updateInventory 方法的事務傳播行為(REQUIRES_NEW)不會生效。

解決方法:

將事務方法拆分到不同的類中
將 updateInventory 方法移到另一個服務類中,通過依賴注入調用。

@Service
public class OrderService {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private InventoryService inventoryService;
    @Transactional
    public void createOrder(Order order) {
        // 保存訂單
        orderRepository.save(order);
        // 調用另一個服務類的事務方法
        inventoryService.updateInventory(order.getProductId(), order.getQuantity());
    }
}
@Service
public class InventoryService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void updateInventory(Long productId, int quantity) {
        // 更新庫存邏輯
    }
}

事務的超時設置

可以通過 @Transactional(timeout = 10) 設置事務的超時時間(單位為秒)。如果事務執(zhí)行時間超過指定時間,事務將自動回滾。

@Service
public class ReportService {
    @Autowired
    private ReportRepository reportRepository;
    @Transactional(timeout = 10) // 設置事務超時時間為 10 秒
    public void generateReport() {
        // 模擬耗時操作
        for (int i = 0; i < 1000000; i++) {
            reportRepository.save(new Report("Report " + i));
        }
    }
}

在上面的示例中,如果 generateReport 方法的執(zhí)行時間超過 10 秒,事務將自動回滾。

6. 總結

Spring Boot 提供了強大的事務管理功能,通過 @Transactional 注解可以輕松實現(xiàn)事務的控制。在實際開發(fā)中,需要根據(jù)業(yè)務需求選擇合適的傳播行為和隔離級別,同時注意事務方法的可見性和自我調用問題。

通過本文的介紹,相信你已經掌握了 Spring Boot 中事務的基本用法。如果你有更多問題,歡迎在評論區(qū)留言討論!

到此這篇關于Spring Boot 中事務的用法詳解的文章就介紹到這了,更多相關Spring Boot 事務的用法內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java多線程Runable售票系統(tǒng)實現(xiàn)過程解析

    Java多線程Runable售票系統(tǒng)實現(xiàn)過程解析

    這篇文章主要介紹了Java多線程Runable售票系統(tǒng)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-06-06
  • 通過入門demo簡單了解netty使用方法

    通過入門demo簡單了解netty使用方法

    這篇文章主要介紹了通過入門demo簡單了解netty使用方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-12-12
  • MyBatis動態(tài)創(chuàng)建表的實例代碼

    MyBatis動態(tài)創(chuàng)建表的實例代碼

    在項目需求中,我們經常會遇到動態(tài)操作數(shù)據(jù)表的需求,常見的我們會把日志、設備實時位置信息等存入數(shù)據(jù)表,并且以一定時間段生成一個表來存儲。接下來通過本文給大家介紹MyBatis動態(tài)創(chuàng)建表的方法,感興趣的朋友一起看看吧
    2018-07-07
  • 基于CyclicBarrier和CountDownLatch的使用區(qū)別說明

    基于CyclicBarrier和CountDownLatch的使用區(qū)別說明

    這篇文章主要介紹了基于CyclicBarrier和CountDownLatch的使用區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-09-09
  • SpringBoot整合mybatis常見問題(小結)

    SpringBoot整合mybatis常見問題(小結)

    這篇文章主要介紹了SpringBoot整合mybatis常見問題(小結),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Java Socket報錯打開文件過多的問題

    Java Socket報錯打開文件過多的問題

    這篇文章主要介紹了Java Socket報錯打開文件過多的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Mybatis Generator Plugin悲觀鎖實現(xiàn)示例

    Mybatis Generator Plugin悲觀鎖實現(xiàn)示例

    本文將從悲觀鎖為例,讓你快速了解如何實現(xiàn)Mybatis Generator Plugin。文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 解決Java項目中request流只能獲取一次的問題

    解決Java項目中request流只能獲取一次的問題

    Java項目開發(fā)中可能存在以下幾種情況,你需要在攔截器中統(tǒng)一攔截請求和你項目里可能需要搞一個統(tǒng)一的異常處理器,這兩種情況是比較常見的,本文將給大家介紹如何解決Java項目中request流只能獲取一次的問題,需要的朋友可以參考下
    2024-02-02
  • SpringBoot整合logback日志的詳細步驟

    SpringBoot整合logback日志的詳細步驟

    這篇文章主要介紹了SpringBoot整合logback日志的詳細步驟,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-05-05
  • 淺析我對 String、StringBuilder、StringBuffer 的理解

    淺析我對 String、StringBuilder、StringBuffer 的理解

    StringBuilder、StringBuffer 和 String 一樣,都是用于存儲字符串的。這篇文章談談小編對String、StringBuilder、StringBuffer 的理解,感興趣的朋友跟隨小編一起看看吧
    2020-05-05

最新評論