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

如何合理使用Spring的事務(wù)方式

 更新時間:2025年05月13日 08:34:45   作者:找不到、了  
這篇文章主要介紹了如何合理使用Spring的事務(wù)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Spring Framework 提供了全面的事務(wù)管理功能,以確保在應(yīng)用程序中操作的原子性、一致性、隔離性和持久性(即 ACID 特性)。

事務(wù)管理是重要的,尤其是在涉及到數(shù)據(jù)庫操作時,以確保數(shù)據(jù)的完整性和一致性。

1、介紹

1.1、底層構(gòu)造

Spring事務(wù)管理高層抽象主要包括3個接口,Spring的事務(wù)主要是由他們共同完成的:

  • PlatformTransactionManager:事務(wù)管理器—主要用于平臺相關(guān)事務(wù)的管理
  • TransactionDefinition:事務(wù)定義信息(隔離、傳播、超時、只讀)—通過配置如何進行事務(wù)管理。
  • TransactionStatus:事務(wù)具體運行狀態(tài)—事務(wù)管理過程中,每個時間點事務(wù)的狀態(tài)信息。

1.1.事務(wù)管理器

PlatformTransactionManager該接口提供三個方法:

  • commit:提交事務(wù)
  • rollback:回滾事務(wù)
  • getTransaction:獲取事務(wù)狀態(tài)

1.2.事務(wù)定義信息

TransactionDefinition該接口主要提供的方法:

  • getIsolationLevel:隔離級別獲取
  • getPropagationBehavior:傳播行為獲取
  • getTimeout:獲取超時時間
  • isReadOnly 是否只讀(保存、更新、刪除—對數(shù)據(jù)進行操作-變成可讀寫的,查詢-設(shè)置這個屬性為true,只能讀不能寫)

1.3.事務(wù)狀態(tài)

TransactionStatus代表獲取事務(wù)的狀態(tài)。

	try {
		操作
	} catch (){
		rollback
	} finally {
		commit 
}

1.4.聯(lián)系

用戶管理事務(wù),先配置事務(wù)管理方案TransactionDefinition、管理事務(wù)通過TransactionManager完成,TransactionManager根據(jù) TransactionDefinition進行事務(wù)管理,

在事務(wù)運行過程中,每個時間點都可以通過獲取TransactionStatus了解事務(wù)運行狀態(tài)!

1.2、特點

定義

  • 事務(wù)是一個操作序列,這些操作要么全部成功,要么全部失敗。無法將部分操作視為成功,其他部分則視為失敗。因此,事務(wù)是一種確保數(shù)據(jù)一致性和完整性的重要手段。

ACID 特性

  • 原子性(Atomicity): 事務(wù)內(nèi)的所有操作要么全部成功,要么全部失敗。
  • 一致性(Consistency): 事務(wù)必須使數(shù)據(jù)庫從一個一致的狀態(tài)轉(zhuǎn)變到另一個一致的狀態(tài)。
  • 隔離性(Isolation): 一個事務(wù)的執(zhí)行不能被其他事務(wù)干擾,確保并發(fā)執(zhí)行下的每個事務(wù)都是在其自己的上下文中執(zhí)行。
  • 持久性(Durability): 事務(wù)一旦提交,其結(jié)果便永久保存,即使系統(tǒng)故障也不會丟失。

1.3、原理

常見面試題:事務(wù)的原理

Spring 事務(wù)的底層實現(xiàn)主要使用的技術(shù):AOP(動態(tài)代理) + ThreadLocal + try/catch。

1.動態(tài)代理AOP:

基本所有要進行邏輯增強的地方都會用到動態(tài)代理,AOP 底層也是通過動態(tài)代理實現(xiàn)。

2.事務(wù)同步管理器(TransactionSynchronizationManager)

Spring使用線程局部變量(ThreadLocal)來管理事務(wù)資源:

  • ThreadLocal:主要用于線程間的資源隔離,以此實現(xiàn)不同線程可以使用不同的數(shù)據(jù)源、隔離級別等等。
public abstract class TransactionSynchronizationManager {
    private static final ThreadLocal<Map<Object, Object>> resources =
        new NamedThreadLocal<>("Transactional resources");
    
    private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
        new NamedThreadLocal<>("Transaction synchronizations");
    
    private static final ThreadLocal<String> currentTransactionName =
        new NamedThreadLocal<>("Current transaction name");
    
    private static final ThreadLocal<Boolean> currentTransactionReadOnly =
        new NamedThreadLocal<>("Current transaction read-only status");
    
    private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
        new NamedThreadLocal<>("Current transaction isolation level");
    
    private static final ThreadLocal<Boolean> actualTransactionActive =
        new NamedThreadLocal<>("Actual transaction active");
}

3.try/catch:

最終是執(zhí)行 commit 還是 rollback,是根據(jù)業(yè)務(wù)邏輯處理是否拋出異常來決定。

Spring 事務(wù)的核心邏輯偽代碼如下:

public void invokeWithinTransaction() {
    // 1.事務(wù)資源準備
    try {
        // 2.業(yè)務(wù)邏輯處理,也就是調(diào)用被代理的方法
    } catch (Exception e) {
        // 3.出現(xiàn)異常,進行回滾并將異常拋出
    } finally {
        // 現(xiàn)場還原:還原舊的事務(wù)信息
    }
    // 4.正常執(zhí)行,進行事務(wù)的提交
    // 返回業(yè)務(wù)邏輯處理結(jié)果
}

4.流程

@Transactional方法調(diào)用
   │
   ↓
TransactionInterceptor攔截
   │
   ↓
獲取事務(wù)屬性(@Transactional配置)
   │
   ↓
根據(jù)傳播行為決定是否創(chuàng)建新事務(wù)
   │
   ↓
TransactionSynchronizationManager綁定資源到當前線程
   │
   ↓
執(zhí)行業(yè)務(wù)方法
   │
   ┌─────────┴──────────┐
   ↓                    ↓
方法成功             方法拋出異常
   │                    │
   ↓                    ↓
提交事務(wù)              判斷是否需要回滾
   │                    │
   ↓                    ↓
清理線程資源           回滾事務(wù)
   │                    │
   ↓                    ↓
返回結(jié)果              拋出異常

2. Spring 的事務(wù)管理

Spring 提供了強大的事務(wù)管理功能,包括編程式和聲明式事務(wù)管理。

1、聲明式事務(wù)管理

(xml和注解形式)

特點

  • 易于使用:只需在方法上添加注解或在配置文件中定義事務(wù)規(guī)則即可啟用事務(wù)管理。
  • 非侵入性:事務(wù)管理邏輯與業(yè)務(wù)邏輯分離,不會干擾業(yè)務(wù)邏輯代碼。
  • 可配置性:可以靈活地配置事務(wù)的傳播行為、隔離級別、超時和回滾規(guī)則等。
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UserService {

    @Transactional // 默認傳播行為為 REQUIRED
    public void createUser(String username) {
        System.out.println("User " + username + " created.");
        // 調(diào)用另一個方法
        addUser(username);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW) // 新事務(wù)
    public void addUser(String username) {
        System.out.println("User " + username + " added in a new transaction.");
    }
    
    @Transactional(propagation = Propagation.NESTED) // 嵌套事務(wù)
    public void updateUser(String username) {
        System.out.println("Updating user: " + username);
    }
}

輸出:

在調(diào)用 createUser 方法之后,如果內(nèi)部調(diào)用 addUser,因為 addUser 不會使用aop代理,

這也意味著,addUser 的成功或失敗不會影響到 createUser 所在的原有事務(wù)。

2、編程式事務(wù)

通過TransactionTemplate手動管理事務(wù)。這里不過多講解,實際使用較少。

在代碼中顯式地管理事務(wù)的開始、提交和回滾。這種方式更加靈活,但同時也增加了代碼的復(fù)雜性。

有興趣的可以參考:

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private PlatformTransactionManager transactionManager;

    public void createUser(User user) {
        TransactionDefinition def = new DefaultTransactionDefinition();
        TransactionStatus status = transactionManager.getTransaction(def);

        try {
            userRepository.save(user);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
            throw e;
        }
    }
}

和JDBC相比:

  • 不需要開始或是關(guān)閉connection(可能還有try-finally的語法),相對應(yīng)的,使用的是Transaction callbacks。
  • 也不需要手動的catch SQLExceptions,因為Spring會把這個異常當作runtime exceptions來處理。
  • 當然想要使用TransactionTemplate,需要先設(shè)置TransactionManager,并需要傳入dataSource。這些都可以配置成Spring的bean,放到context中。

3、事務(wù)傳播行為

Spring 提供了多種事務(wù)傳播行為來定義一個事務(wù)方法應(yīng)如何參與現(xiàn)有事務(wù)。常用的傳播行為包括:

對事務(wù)比較積極的三個傳播行為:

  • REQUIRED: 使用現(xiàn)有的事務(wù),如果沒有,則創(chuàng)建一個新的事務(wù)(默認值)。
  • REQUIRES_NEW: 總是創(chuàng)建一個新的事務(wù),并掛起當前事務(wù)。
  • MANDATORY: 必須存在一個當前事務(wù),若沒有則拋出異常。

觀望者:

  • NESTED: 在當前事務(wù)中執(zhí)行一個嵌套事務(wù)(支持保存點)。

比較佛系的三個傳播行為

  • SUPPORTS: 存在則加入,不存在,則非事務(wù)運行。
  • PROPAGATION_NOT_SUPPORTED:不能參與。
  • PROPAGATION_NEVER:不參與,參與事務(wù),則拋出異常。

3、事務(wù)的隔離級別

1、并發(fā)事務(wù)的問題

2、隔離級別

3、如何設(shè)置

(1) 聲明式事務(wù)(通過 @Transactional 注解)

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

(2) 編程式事務(wù)(通過 TransactionTemplate

@Autowired
private TransactionTemplate transactionTemplate;

public void executeInTransaction() {
    transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
    transactionTemplate.execute(status -> {
        // 業(yè)務(wù)邏輯
        return null;
    });
}

4、選擇隔離級別

優(yōu)先使用默認值(ISOLATION_DEFAULT)

  • 除非有明確需求,否則依賴數(shù)據(jù)庫默認配置,避免框架與數(shù)據(jù)庫行為不一致。

平衡性能與一致性

  • 高并發(fā)場景 → READ_COMMITTED(減少鎖競爭)。
  • 強一致性場景 → REPEATABLE_READSERIALIZABLE(需測試性能影響)。

5、查看隔離級別

  • 數(shù)據(jù)庫日志:執(zhí)行 SHOW VARIABLES LIKE 'transaction_isolation';(MySQL)或等效命令。
  • 代碼調(diào)試:通過 TransactionSynchronizationManager.getCurrentTransactionIsolationLevel() 獲取。

4、事務(wù)失效

1. 直接調(diào)用同一類中的事務(wù)方法

在同一類中直接調(diào)用被事務(wù)注解的方法會導(dǎo)致事務(wù)失效。因為 Spring 的 AOP 代理只在通過 Spring 管理的 Bean 進行調(diào)用時才會生效。

代碼示例:

@Service
public class UserServiceTxImpl implements UserServiceTx {

   
    @Transactional(rollbackFor = RuntimeException.class) // 默認傳播行為為 REQUIRED
    public void createUser(String username) {
        System.out.println("User " + username + " created.");
        // 調(diào)用另一個方法
        addUser(username);
        System.out.println("User " + username + " createUsed ");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = RuntimeException.class) // 新事務(wù)
    public void addUser(String username) {
        System.out.println("User " + username + " added in a new transaction.");
        throw new RuntimeException("Exception in innerMethod");
    }


}

解決方案

1、可以在本bean里面直接使用spring注入的方式:不過會導(dǎo)致循環(huán)依賴。

2、 AopContext.currentProxy();

@Service
public class UserServiceTxImpl implements UserServiceTx {

    @Autowired
    private UserServiceTxImpl userService;

    @Transactional(rollbackFor = RuntimeException.class) // 默認傳播行為為 REQUIRED
    public void createUser(String username) {
        System.out.println("User " + username + " created.");
        // 調(diào)用另一個方法
        userService.addUser(username);
        System.out.println("User " + username + " createUsed ");
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = RuntimeException.class) // 新事務(wù)
    public void addUser(String username) {
        System.out.println("User " + username + " added in a new transaction.");
        throw new RuntimeException("Exception in innerMethod");
    }


}
UserServiceTx o = (UserServiceTx) AopContext.currentProxy();

2. 直接使用 SQL 操作

如果你在事務(wù)管理的方法中執(zhí)行了原生的 SQL 操作(例如通過 JDBC),而沒有通過 Spring 的事務(wù)管理進行處理,事務(wù)可能會失效。

@Service
public class UserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional
    public void createUser(String username) {
        System.out.println("In createUser method");

        // 直接使用 JDBC 操作,不通過 Spring 數(shù)據(jù)庫訪問
        jdbcTemplate.execute("INSERT INTO users (username) VALUES ('" + username + "')");

        // 模擬異常
        throw new RuntimeException("Intentional exception"); // 模擬拋出異常
    }
}

這些操作不通過 Spring 的數(shù)據(jù)訪問層,將會導(dǎo)致事務(wù)管理操作失效。

3. 使用不正常的異常處理

Spring 只對運行時異常(RuntimeException)自動回滾,而對檢查性異常(Exception)默認不回滾。

如果需要回滾需要rollbackFor指定回滾異常。

  @Transactional(rollbackFor = RuntimeException.class) // 默認傳播行為為 REQUIRED
    public void createUser(String username) {
        System.out.println("User " + username + " created.");
        // 調(diào)用另一個方法
        userService.addUser(username);
        System.out.println("User " + username + " createUsed ");
    }

4、非public方法,目前事務(wù) 只支持pub

5、mysql的存儲引擎說mysaim不支持事務(wù)。

6、對異常進行try catch捕獲,導(dǎo)致無法生效。

7、事務(wù)處理的響應(yīng)超時。

總結(jié)

Spring 的事務(wù)管理功能為開發(fā)者提供了一種高效且靈活的方式來處理復(fù)雜的數(shù)據(jù)庫操作,確保數(shù)據(jù)的一致性和完整性,通過注解或 XML 配置,可以很容易地查看哪些方法是事務(wù)性的,邏輯結(jié)構(gòu)清晰。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java 數(shù)據(jù)結(jié)構(gòu)進階二叉樹題集上

    Java 數(shù)據(jù)結(jié)構(gòu)進階二叉樹題集上

    二叉樹可以簡單理解為對于一個節(jié)點來說,最多擁有一個上級節(jié)點,同時最多具備左右兩個下級節(jié)點的數(shù)據(jù)結(jié)構(gòu)。本文將帶你通過實際題目來熟練掌握
    2022-04-04
  • java數(shù)字轉(zhuǎn)漢字工具類詳解

    java數(shù)字轉(zhuǎn)漢字工具類詳解

    這篇文章主要為大家詳細介紹了java數(shù)字轉(zhuǎn)漢字工具類的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • SpringBoot集成內(nèi)存數(shù)據(jù)庫hsqldb的實踐

    SpringBoot集成內(nèi)存數(shù)據(jù)庫hsqldb的實踐

    hsqldb只需要添加對應(yīng)的依賴,然后在配置文件進行配置。不需要安裝一個數(shù)據(jù)庫,本文就來介紹一下具體使用,感興趣的可以了解一下
    2021-09-09
  • Java多線程實現(xiàn)Runnable方式

    Java多線程實現(xiàn)Runnable方式

    這篇文章主要為大家詳細介紹了Java多線程如何實現(xiàn)Runnable方式,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java?Map集合中取鍵和值的4種方式舉例

    java?Map集合中取鍵和值的4種方式舉例

    Java中的Map是一種鍵值對存儲的數(shù)據(jù)結(jié)構(gòu),其中每個鍵都唯一,與一個值相關(guān)聯(lián),這篇文章主要給大家介紹了關(guān)于java?Map集合中取鍵和值的4種方式,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-01-01
  • ThreadLocal工作原理及用法案例

    ThreadLocal工作原理及用法案例

    本文詳細講解了ThreadLocal工作原理及用法案例,文中通過示例代碼介紹的非常詳細。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • mybatis自定義參數(shù)類型轉(zhuǎn)換器數(shù)據(jù)庫字段加密脫敏

    mybatis自定義參數(shù)類型轉(zhuǎn)換器數(shù)據(jù)庫字段加密脫敏

    這篇文章主要為大家介紹了mybatis自定義參數(shù)類型轉(zhuǎn)換器數(shù)據(jù)庫字段加密脫敏,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-09-09
  • springboot+springmvc實現(xiàn)登錄攔截

    springboot+springmvc實現(xiàn)登錄攔截

    這篇文章主要介紹了springboot+springmvc實現(xiàn)登錄攔截,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • Mybatis-Plus中and()和or()的使用與原理詳解

    Mybatis-Plus中and()和or()的使用與原理詳解

    最近發(fā)現(xiàn)MyBatisPlus還是挺好用的,下面這篇文章主要給大家介紹了關(guān)于Mybatis-Plus中and()和or()的使用與原理的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-09-09
  • 當mybatis返回值遇見內(nèi)部類的問題

    當mybatis返回值遇見內(nèi)部類的問題

    這篇文章主要介紹了當mybatis返回值遇見內(nèi)部類的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-12-12

最新評論

吐鲁番市| 永昌县| 绿春县| 普兰县| 格尔木市| 体育| 涟水县| 新平| 南澳县| 堆龙德庆县| 靖安县| 永丰县| 兰州市| 奇台县| 五大连池市| 介休市| 江安县| 宜城市| 高州市| 呈贡县| 科技| 尚志市| 黑龙江省| 东港市| 元氏县| 自治县| 彝良县| 象州县| 永修县| 五台县| 宁德市| 寻乌县| 河曲县| 瑞金市| 桂东县| 青河县| 友谊县| 蕲春县| 东台市| 齐齐哈尔市| 辽宁省|