欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解在SpringBoot中@Transactional事物操作和事物無效問題排查

 更新時(shí)間:2021年06月29日 17:58:43   作者:hanchao5272  
這篇文章主要介紹了詳解在SpringBoot中@Transactional事物操作和事物無效問題排查,本文詳細(xì)的介紹了SpringBoot中集成使用@Transactional注解操作事物以及事物開啟后無效的問題排查,需要的朋友可以參考下

1.spring事務(wù)管理簡述

兩種事務(wù)管理方式:

  1. 編碼式事務(wù)管理:將事務(wù)控制代碼編寫在業(yè)務(wù)代碼之中。
  2. 聲明式事務(wù)管理:基于AOP(面向切面編程),事務(wù)管理與業(yè)務(wù)邏輯解耦。聲明式事務(wù)管理的兩種實(shí)現(xiàn):
    1. 在配置文件(xml)中配置。
    2. 基于@Transactional注解。

2.SpringBoot中使用@Transactional注解

2.1.開啟事務(wù)注解

在項(xiàng)目主類上,加上注解@EnableTransactionManagement,例如:

@EnableTransactionManagement
public class MySpringBootService extends WebMvcConfigurerAdapter {
    public static void main(String[] args) {
        SpringApplication.run(CoreService.class, args);
    }
}

2.2.在目標(biāo)類、方法上添加注解@Transactional

1. 如果將@Transactional添加到類上,則表示此類的所有方法都開啟事務(wù)管理。如:

   @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
   @Service
   public class MyServiceImpl implements MyService {
     //class body
   }

2. 如果將@Transactional添加到方法上,則表示此方法開啟事務(wù)管理。如:

       @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
       @Override
       public ActivityPo getActivityById(Long id){
         //method body
       }

3. 如果一個(gè)方法上存在@Transactional,且其所屬類上同樣存在@Transactional,則以方法級別的事務(wù)配置為準(zhǔn)。

2.3.細(xì)化事務(wù)配置

關(guān)于@Transactional的可配置參數(shù)有很多,主要有propagation、rollbackFor等,可以適用于不同場景,這里不細(xì)說。

3.@Transactional事務(wù)實(shí)現(xiàn)機(jī)制

3.1.整體事務(wù)控制流程

  1. 當(dāng)@Transactional注解的方法被類外部的代碼調(diào)用時(shí),Spring在運(yùn)行時(shí)為方法所在類生成一個(gè)AOP代理對象。
  2. 代理對象根據(jù)@Transactional的屬性,決定是否由事務(wù)攔截器TransactionInterceptor對此方法進(jìn)行事務(wù)攔截。
  3. 在進(jìn)行事務(wù)攔截時(shí),會(huì)先開啟事務(wù),然后執(zhí)行業(yè)務(wù)代碼,根據(jù)執(zhí)行是否出現(xiàn)異常,通過抽象事務(wù)管理器AbstractPlatformTransactionManager來進(jìn)行rollback或者commit。

3.2.Spring AOP的兩種代理

  1. Spring AOP有兩種CglibAopProxy和JdkDynamicAopProxy,其中:
  2. CglibAopProxy在其內(nèi)部類DynamicAdvisedInterceptor的intercept()方法中,判斷是否進(jìn)行事務(wù)攔截。
  3. JdkDynamicAopProxy在其invoke()方法中,判斷是否進(jìn)行事務(wù)攔截。

3.3.事務(wù)操作的底層實(shí)現(xiàn)

  1. 抽象事務(wù)管理器AbstractPlatformTransactionManager的rollback和commit都需要具體的實(shí)現(xiàn)類進(jìn)行實(shí)現(xiàn)。
  2. 抽象事務(wù)管理器AbstractPlatformTransactionManager的父級接口是PlatformTransactionManager。
  3. 存在很多事務(wù)管理器實(shí)現(xiàn)類,例如DataSourceTransactionManager等。
  4. 不同的事務(wù)管理器管理不同的數(shù)據(jù)資源 DataSource,比如DataSourceTransactionManager管理者JDBC數(shù)據(jù)源。
  5. 應(yīng)確保被調(diào)用方法中使用的數(shù)據(jù)源都加載了事務(wù)管理器。

4.@Transactional使用注釋實(shí)現(xiàn)及問題排查

4.1.數(shù)據(jù)庫引擎是否支持事務(wù)?

  • MySql的引擎MyIsam不支持事務(wù)。
  • 如需事務(wù)控制生效,則庫和表的引擎必須是InnoDB。

4.3.注解所在的類是否被加載成Bean?

  • 章節(jié)3.1中第1條提到,需要在運(yùn)行時(shí)為類生成代理對象。那么前提是這個(gè)類一定被Spring管理并加載成了一個(gè)Bean對象。
  • 確保所在類是否被@Component、@Service、@Controller等等注解注釋。

4.2.注解所在方法是否為public修飾的?

  • 章節(jié)3.2中,提到兩種AOP代理分別在intercept()和invoke()方法判斷是否進(jìn)行事務(wù)攔截。
  • 這兩個(gè)方法都會(huì)間接調(diào)用AbstractFallbackTransactionAttributeSource類的computeTransactionAttribute方法來獲取事務(wù)控制的相關(guān)屬性。這其中有以下一段代碼:
	/**
	 * Same signature as {@link #getTransactionAttribute}, but doesn't cache the result.
	 * {@link #getTransactionAttribute} is effectively a caching decorator for this method.
	 * <p>As of 4.1.8, this method can be overridden.
	 * @since 4.1.8
	 * @see #getTransactionAttribute
	 */
	protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
		// Don't allow no-public methods as required.
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}
    
    //...
  }
  • 這段代碼會(huì)導(dǎo)致no-public的方法無法進(jìn)入事務(wù)控制。
  • 所以,一定要確保自己需要進(jìn)行事務(wù)控制的方法包含public修飾符。

4.5.是否發(fā)生了自調(diào)用問題?

  • 章節(jié)3.1中第1條強(qiáng)調(diào):只有當(dāng)事務(wù)方法被當(dāng)前類以外的代碼調(diào)用時(shí),才會(huì)才由 Spring 生成的代理對象來管理。
  • 上述邏輯會(huì)造成自調(diào)用問題:當(dāng)事務(wù)方法被本類內(nèi)部方法調(diào)用時(shí),@Transactional并不生效。
  • 自調(diào)用示例代碼:
@Service
public class PersonServiceImpl implements PersonService{
  @Resource
  private PersonDao personDao;
  
  public void insertPerson(Person person){
    //自調(diào)用
    personService.insert(person);
    
    //其他代碼
    personDao.insertLog...
	}
  
  @Transactional(rollbackFor = Exception.class)
  public void insert(Person person){
    personDao.insert(person);
	}
}
  • 上述代碼中,如果業(yè)務(wù)邏輯從非事務(wù)方法insertPerson()開始,在其中調(diào)用了事務(wù)方法insert(),則當(dāng)insert()異常時(shí),事務(wù)控制無效。
  • 簡單說,就是在同一類中,非事務(wù)方法A調(diào)用了事務(wù)方法B,則當(dāng)事務(wù)方法B異常,事務(wù)控制無效,A和B都不會(huì)回滾。
  • 那么,在同一類中,事務(wù)方法A調(diào)用了非事務(wù)方法B,然后非事務(wù)方法B調(diào)用了事務(wù)方法C,事務(wù)是否生效?答案:是。因?yàn)槭聞?wù)方法A在被外部代碼調(diào)用時(shí),已經(jīng)開啟了事務(wù)管理。

4.6.所用數(shù)據(jù)源是否加載了事務(wù)管理器?

  • 章節(jié)3.3中第5條提到:應(yīng)確保被調(diào)用方法中使用的數(shù)據(jù)源都加載了事務(wù)管理器。
  • 在SpringBoot項(xiàng)目中,如果是單數(shù)據(jù)源,那么系統(tǒng)會(huì)默認(rèn)為單數(shù)據(jù)源配置事務(wù)管理器DataSourceTransactionManager。
  • 在SpringBoot項(xiàng)目中,如果是多數(shù)據(jù)源,則一定確保所有的數(shù)據(jù)源都配置了事務(wù)管理器。
  • 關(guān)于多數(shù)據(jù)源的配置方法可以參考: https://blog.csdn.net/hanchao5272/article/details/81209552
  • 事務(wù)管理器的手動(dòng)配置方法,可以參考如下:
@Bean
@Primary
public PlatformTransactionManager primaryTransactionManager(@Qualifier("sqlDataSource") DataSource sqlDataSource) {
  return new DataSourceTransactionManager(sqlDataSource);
}

4.4.觸發(fā)回滾的異常是否配置正確?

  • 默認(rèn)情況下,事務(wù)回歸針對的是uncheck的異常(運(yùn)行時(shí)異常)或ERROR。
  • 默認(rèn)情況下,check的異常并不會(huì)觸發(fā)回滾,如FileNotFoundException。
  • 如果想要簡單的配置成針對所有異常都回滾,可以這么做:
@Transactional(rollbackFor = Exception.class)

4.5.@Transactional的擴(kuò)展配置propagation是否正確?

  • 一般情況下,propagation屬性無需配置。其會(huì)使用默認(rèn)配置,即:Propagation.REQUIRED。
  • 有些propagation屬性會(huì)導(dǎo)致事務(wù)不會(huì)觸發(fā),一定要注意:
    • SUPPORTS: 如果存在事務(wù),則進(jìn)入事務(wù);否則,以非事務(wù)方式運(yùn)行。
    • NOT_SUPPORTED: 如果存在事務(wù),則掛起事務(wù),并以非事務(wù)方式運(yùn)行。
    • NEVER: 以非事務(wù)形式運(yùn)行,如果存在事務(wù),則拋出異常。

4.7.事務(wù)管理的可選配置是否正確?

在SpringBoot中,關(guān)于事務(wù)的配置有兩個(gè)可選配置(一般無需配置):

  1. Springboot啟動(dòng)類的@EnableTransactionManagement。
  2. Springboot配置文件的rollback-on-commit-failure屬性:
# yaml配置
spring:
  transaction:
    rollback-on-commit-failure: true
    
# properties配置
spring.transaction.rollback-on-commit-failure=true

請確保上述配置都是正確的(或者未配置)。

到此這篇關(guān)于詳解在SpringBoot中@Transactional事物操作和事物無效問題排查的文章就介紹到這了,更多相關(guān)SpringBoot使用@Transactional內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java實(shí)現(xiàn)動(dòng)態(tài)上傳多個(gè)文件并解決文件重名問題

    java實(shí)現(xiàn)動(dòng)態(tài)上傳多個(gè)文件并解決文件重名問題

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)動(dòng)態(tài)上傳多個(gè)文件,并解決文件重名問題的方法,感興趣的小伙伴們可以參考一下
    2016-03-03
  • SpringBoot操作Mongodb的實(shí)現(xiàn)示例

    SpringBoot操作Mongodb的實(shí)現(xiàn)示例

    本文主要介紹了SpringBoot操作Mongodb的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • idea搭建mybatis環(huán)境配置全過程

    idea搭建mybatis環(huán)境配置全過程

    本文介紹了如何以IDEA搭建MyBatis環(huán)境配置的方法,包括步驟和注意事項(xiàng),通過本文的介紹,可以輕松地以IDEA搭建MyBatis環(huán)境配置,提高開發(fā)效率
    2023-10-10
  • 詳解spring boot集成ehcache 2.x 用于hibernate二級緩存

    詳解spring boot集成ehcache 2.x 用于hibernate二級緩存

    本篇文章主要介紹了詳解spring boot集成ehcache 2.x 用于hibernate二級緩存,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • 為何Java8需要引入新的日期與時(shí)間庫

    為何Java8需要引入新的日期與時(shí)間庫

    這篇文章主要給大家介紹了關(guān)于Java8為什么需要引入新的日期與時(shí)間庫的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • 使用idea生成springboot程序的docker鏡像的操作指南

    使用idea生成springboot程序的docker鏡像的操作指南

    這篇文章給大家詳細(xì)的介紹了使用idea生成springboot程序的docker鏡像的操作指南,文中通過圖文結(jié)合給大家講解的非常詳細(xì),具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-12-12
  • Spring Boot 基于注解的 Redis 緩存使用詳解

    Spring Boot 基于注解的 Redis 緩存使用詳解

    本篇文章主要介紹了Spring Boot 基于注解的 Redis 緩存使用詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • Java FileWriter輸出換行操作

    Java FileWriter輸出換行操作

    這篇文章主要介紹了Java FileWriter輸出換行操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Spring Native實(shí)現(xiàn)0.059s啟動(dòng)一個(gè)SpringBoot項(xiàng)目

    Spring Native實(shí)現(xiàn)0.059s啟動(dòng)一個(gè)SpringBoot項(xiàng)目

    Spring Native是Spring框架的一個(gè)子項(xiàng)目,旨在提供一種將Spring應(yīng)用程序編譯為本地可執(zhí)行文件的方法,從而提高啟動(dòng)時(shí)間和資源效率,本文主要介紹了Spring Native實(shí)現(xiàn)0.059s啟動(dòng)一個(gè)SpringBoot項(xiàng)目,感興趣的可以了解一下
    2024-02-02
  • MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    MyBatis 中 ${}和 #{}的正確使用方法(千萬不要亂用)

    這篇文章主要介紹了MyBatis 中 ${}和 #{}的正確使用方法,本文給大家提到了MyBatis 中 ${}和 #{}的區(qū)別,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評論