溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring事務是什么及怎么實現(xiàn)

發(fā)布時間:2023-05-05 15:43:20 來源:億速云 閱讀:248 作者:iii 欄目:開發(fā)技術

這篇文章主要講解了“Spring事務是什么及怎么實現(xiàn)”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Spring事務是什么及怎么實現(xiàn)”吧!

什么是Spring事務?

Spring事務是指在Spring框架中對于數(shù)據(jù)庫操作的一種支持,它通過對一組數(shù)據(jù)庫操作進行整體控制來保證數(shù)據(jù)的一致性和完整性。Spring事務可以保證在一組數(shù)據(jù)庫操作執(zhí)行時,要么所有操作都執(zhí)行成功,要么所有操作都回滾到之前的狀態(tài),從而避免了數(shù)據(jù)不一致的情況。

Spring事務實現(xiàn)方式

Spring事務可以通過編程式事務和聲明式事務兩種方式來實現(xiàn)。編程式事務需要在代碼中手動控制事務的開始、提交和回滾等操作,而聲明式事務則是通過在配置文件中聲明事務的切入點和通知等信息來自動控制事務的行為。

Spring編程式事務

Spring編程式事務需要在代碼中獲取事務管理器,并通過該事務管理器獲取事務對象,然后使用該事務對象來控制事務的開始、提交和回滾等操作。

public void transferMoney(Account fromAccount, Account toAccount, double amount) {
    TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
        fromAccount.withdraw(amount);
        toAccount.deposit(amount);
        transactionManager.commit(status);
    } catch (Exception e) {
        transactionManager.rollback(status);
    }
}

在上面的代碼中,首先通過transactionManager.getTransaction方法獲取事務對象status,然后在try塊中執(zhí)行轉賬操作,最后通過transactionManager.commit(status)提交事務。如果在轉賬操作中發(fā)生了異常,則會通過transactionManager.rollback(status)回滾事務。

編程式事務的優(yōu)點是靈活性高,可以根據(jù)具體的業(yè)務需求來靈活控制事務的行為。不過缺點是代碼冗長,可讀性差,而且容易出現(xiàn)錯誤。

Spring聲明式事務

Spring聲明式事務需要在配置文件中聲明事務管理器、事務通知等元素,然后在需要使用事務的方法上添加事務切面的注解即可。

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"/>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="transferMoney" propagation="REQUIRED"/>
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="transferPointcut" expression="execution(* com.example.TransferService.transferMoney(..))"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="transferPointcut"/>
</aop:config>

在上面的配置文件中,首先聲明了事務管理器transactionManager,然后定義了事務通知txAdvice,該通知會在transferMoney方法執(zhí)行時進行事務管理。最后通過aop:configaop:advisor來將txAdvice應用于transferPointcut定義的切入點上。

聲明式事務的優(yōu)點是通過配置文件來管理事務,避免了在代碼中手動控制事務的繁瑣和容易出錯的問題。不過缺點是靈活性較差,不能根據(jù)具體的業(yè)務需求來靈活控制事務的行為。

聲明式事務注解方式

Spring聲明式事務也可以通過注解的方式來實現(xiàn)。具體來說,可以在需要使用事務的方法上添加@Transactional注解,并通過該注解的屬性來指定事務的傳播機制、隔離級別、超時時間等信息。

@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3600)
public void transferMoney(Account fromAccount, Account toAccount, double amount) {
    fromAccount.withdraw(amount);
    toAccount.deposit(amount);
}

在上面的代碼中,通過@Transactional注解來聲明了事務的傳播機制為Propagation.REQUIRED,隔離級別為Isolation.DEFAULT,超時時間為3600秒。在方法執(zhí)行時,Spring會根據(jù)注解中的信息自動管理事務的行為。

注解式聲明事務的優(yōu)點是代碼簡潔、可讀性好,靈活性和可用性高,容易維護和調(diào)試。但是它也有一些缺點,例如注解的使用可能會導致代碼分散,而且無法通過配置文件來管理事務,而且可能會引入一些意想不到的問題。

@Transactional注解的常用參數(shù)包括:

  • value:該屬性可以用來指定事務管理器的名稱,如果只有一個事務管理器,則可以省略該屬性。

  • propagation:該屬性用于指定事務的傳播機制,包括REQUIRED、SUPPORTSMANDATORY、REQUIRES_NEWNOT_SUPPORTED、NEVERNESTED共7種。

  • isolation:該屬性用于指定事務的隔離級別,包括DEFAULTREAD_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READSERIALIZABLE共5種。

  • timeout:該屬性用于指定事務的超時時間,單位為秒,默認值為-1,表示沒有超時限制。

  • readOnly:該屬性用于指定事務是否為只讀事務,默認值為false,表示事務可讀可寫。

  • rollbackFor:該屬性用于指定事務回滾的條件,如果出現(xiàn)指定的異常類型,則事務會回滾。

  • noRollbackFor:該屬性用于指定事務不回滾的條件,如果出現(xiàn)指定的異常類型,則事務不會回滾。

除了上述常用參數(shù)外,@Transactional注解還有其他一些參數(shù),例如transactionManager、rollbackForClassName、noRollbackForClassNamevalue等,具體用法可以參考Spring官方文檔。

在使用@Transactional注解時,需要根據(jù)具體的業(yè)務需求來選擇合適的參數(shù),以保證事務的正確性和可靠性。

事務注解失效情況

Spring的聲明式事務注解可能失效的情況包括:

  • 注解被錯誤地放置在了類上而不是方法上。

  • 方法是private或final的,而且它們不能從外部調(diào)用。

  • 方法沒有被公開暴露,也就是說,它們不是公開的方法(public)。

  • 被注解的方法是靜態(tài)的。

  • 被注解的方法依賴于其他未被注解的方法(例如,被注解的方法調(diào)用了一個未被注解的私有方法)。

  • 被注解的方法在另一個類中被調(diào)用。

  • 注解被錯誤地配置了,例如使用了錯誤的名稱或參數(shù)。

  • 類沒有被正確地掃描,因此Spring無法找到應該被注解的方法。

  • 注解屬性propagation設置錯誤

  • 注解屬性rollbackFor設置錯誤

  • 異常被catch捕獲導致@Transactional失效

  • 數(shù)據(jù)庫引擎不支持事務

  • 多個切面的影響也會導致事務失效

如果遇到聲明式事務注解失效的情況,需要檢查上述問題并進行相應的修復。

代碼規(guī)范中強調(diào)

@Transactional事務不要濫用。事務會影響數(shù)據(jù)庫的QPS,另外使用事務的敵方需要考慮各方面的回滾方案,包括緩存回滾、搜索引擎、消息補償、統(tǒng)計修正等。

在使用Spring事務時,需要注意對于事務的傳播機制和隔離級別的設置,以及對于事務的異常處理等問題。正確地使用Spring事務可以提高系統(tǒng)的數(shù)據(jù)一致性和可靠性。

什么是Spring事務傳播機制

Spring事務傳播機制是指在多個事務操作發(fā)生時,如何管理這些操作之間的事務關系。Spring事務傳播機制可以通過Propagation枚舉類中的不同值來指定,共包括七種不同的傳播行為。具體來說,Spring事務傳播機制包括以下七種:

  • REQUIRED:如果當前沒有事務,則創(chuàng)建一個新的事務;如果當前已經(jīng)存在事務,則加入該事務。這是默認的傳播行為。

  • SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式執(zhí)行。

  • MANDATORY:必須在一個已存在的事務中執(zhí)行,否則就拋出TransactionRequiredException異常。

  • REQUIRES_NEW:創(chuàng)建一個新的事務,并在該事務中執(zhí)行;如果當前存在事務,則將當前事務掛起。

  • NOT_SUPPORTED:以非事務方式執(zhí)行操作,如果當前存在事務,則將當前事務掛起。

  • NEVER:以非事務方式執(zhí)行操作,如果當前存在事務,則拋出IllegalTransactionStateException異常。

  • NESTED:如果當前存在事務,則在嵌套事務中執(zhí)行;如果當前沒有事務,則創(chuàng)建一個新的事務。

在使用Spring事務傳播機制時,需要根據(jù)具體的業(yè)務需求來選擇合適的傳播行為,以保證事務的正確性和可靠性。同時,需要注意事務的異常處理等問題,以避免數(shù)據(jù)不一致或丟失的情況發(fā)生。

@Transactional注解中的傳播機制

除了在代碼中使用編程式事務和聲明式事務外,Spring還提供了@Transactional注解來實現(xiàn)事務控制。在使用@Transactional注解時,可以通過propagation屬性來指定事務的傳播機制,例如:

@Transactional(propagation = Propagation.REQUIRED)
public void transferMoney(Account fromAccount, Account toAccount, double amount) {
    fromAccount.withdraw(amount);
    toAccount.deposit(amount);
}

在上面的代碼中,通過propagation屬性來指定了事務的傳播機制為Propagation.REQUIRED,即如果當前沒有事務,則創(chuàng)建一個新的事務;如果當前已經(jīng)存在事務,則加入該事務。

除了Propagation枚舉類中的七種傳播行為外,@Transactional注解還可以通過isolation、timeoutreadOnly等屬性來指定事務的隔離級別、超時時間和只讀事務等信息。

在使用@Transactional注解時,需要根據(jù)具體的業(yè)務需求來選擇合適的傳播行為和其他屬性,以保證事務的正確性和可靠性。

Spring事務的隔離級別

Spring事務的隔離級別是指多個事務之間的隔離程度,它可以通過設置isolation屬性來指定。Spring事務的隔離級別包括以下五種:

  • DEFAULT:默認的隔離級別,由底層數(shù)據(jù)庫引擎決定。

  • READ_UNCOMMITTED:最低的隔離級別,允許讀取未提交的數(shù)據(jù)。該級別會導致“臟讀”、“不可重復讀”和“幻讀”等問題。

  • READ_COMMITTED:只允許讀取已經(jīng)提交的數(shù)據(jù)。該級別可以避免“臟讀”,但可能會導致“不可重復讀”和“幻讀”等問題。

  • REPEATABLE_READ:保證在同一個事務中多次讀取同一數(shù)據(jù)時,該數(shù)據(jù)的值不會發(fā)生變化。該級別可以避免“臟讀”和“不可重復讀”,但可能會導致“幻讀”等問題。

  • SERIALIZABLE:最高的隔離級別,強制事務串行執(zhí)行,避免了“臟讀”、“不可重復讀”和“幻讀”等問題。但是該級別會對性能產(chǎn)生較大的影響,因此一般不建議使用。

在選擇隔離級別時,需要根據(jù)具體的業(yè)務需求來選擇合適的級別。一般來說,如果不需要在事務中讀取未提交的數(shù)據(jù),那么可以選擇READ_COMMITTED級別;如果需要避免“不可重復讀”問題,可以選擇REPEATABLE_READ級別;如果需要避免“幻讀”問題,可以選擇SERIALIZABLE級別。但是需要注意的是,隔離級別越高,事務的并發(fā)性越差,因此需要根據(jù)具體業(yè)務場景來權衡隔離級別和性能。

不可重復讀和幻讀的區(qū)別

不可重復讀和幻讀都是在并發(fā)讀寫數(shù)據(jù)時可能出現(xiàn)的問題。

不可重復讀指的是在一個事務中多次讀取同一數(shù)據(jù),但是由于其他事務的修改,導致兩次讀取的結果不一致。例如,事務A在讀取某個數(shù)據(jù)時,事務B修改了該數(shù)據(jù)并提交,然后事務A再次讀取該數(shù)據(jù)時,得到了不同的結果。

幻讀是指在一個事務中多次讀取同一范圍內(nèi)的數(shù)據(jù),但是由于其他事務的插入操作,導致兩次讀取的結果不一致。例如,事務A在讀取某個范圍內(nèi)的數(shù)據(jù)時,事務B插入了一條數(shù)據(jù)并提交,然后事務A再次讀取該范圍內(nèi)的數(shù)據(jù)時,得到了不同的結果。

不可重復讀和幻讀的區(qū)別在于,不可重復讀是在讀取同一數(shù)據(jù)時出現(xiàn)問題,而幻讀是在讀取同一范圍內(nèi)的數(shù)據(jù)時出現(xiàn)問題。解決不可重復讀的問題可以使用鎖機制或者提高事務的隔離級別,而解決幻讀的問題可以使用鎖機制或者使用更高的隔離級別,例如SERIALIZABLE級別。

rollbackFor屬性

在使用@Transactional注解進行聲明式事務管理時,可以通過rollbackFor屬性來指定哪些異常類型需要回滾事務。需要注意的是,rollbackFor屬性指定的異常類型必須是Throwable類型或其子類,并且必須包含在Spring事務拋出的異常類型之內(nèi)。如果指定的異常類型不正確或不在事務回滾的異常類型之內(nèi),可能會導致事務無法正確回滾或者回滾不完整的問題。

如果需要指定多個異常類型,可以使用數(shù)組的方式進行指定,例如:

@Transactional(rollbackFor = {SQLException.class, IOException.class})
public void doSomething() {
    // ...
}

在上面的代碼中,指定了SQLExceptionIOException兩種異常類型需要回滾事務。默認情況只有RuntimeException和Error會觸發(fā)事務回滾。

除了rollbackFor屬性外,@Transactional注解還有其他一些屬性可以用于指定事務的屬性和行為,包括propagationisolation、timeoutreadOnly等。需要根據(jù)具體的業(yè)務需求來選擇合適的屬性和行為,以保證事務的正確性和可靠性。

感謝各位的閱讀,以上就是“Spring事務是什么及怎么實現(xiàn)”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對Spring事務是什么及怎么實現(xiàn)這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。

AI