面試 Spring 事務有哪些坑

2021-10-10 15:18:43 字數 3908 閱讀 3585

3.6. 怎麼保證 spring 事務內的連線唯一性

4 總結

今天,我們來講 spring 中和事務有關的考題。

因為事務這塊,面試的出現機率很高。而大家工作中 crud 的比較多,沒有好好總結過這塊的知識,因此面試容易支支吾吾答不出來。於是乎接下來你就會接到一張好人卡,如"你很優秀,不適合我們公司!"

主要內容如下:

首先,我們先明白 spring 事務的本質其實就是資料庫對事務的支援。沒有資料庫的事務支援,spring 是無法提供事務功能的。

那麼,我們一般使用 jdbc 操作事務的**如下:

獲取連線 connection con = drivermanager.getconnection();

開啟事務 con.setautocommit(true/false);

執行 crud;

提交事務、回滾事務:con.commit() ,con.rollback();

首先我們要明白, spring 事務回滾機制是這樣的:當所攔截的方法有指定異常丟擲,事務才會自動進行回滾!

因此,如果你默默的吞掉異常,像下面這樣:

@service

public class userservice catch }}

那切面捕捉不到異常,肯定是不會回滾的。

還有就是,預設配置下,事務只會對 error 與 runtimeexception 及其子類這些異常做出回滾。一般的 exception 這些 checked 異常不會發生回滾。如果一般的 exception 想回滾,要做出如下配置:

@transactional(rollbackfor = exception.class)
但是在實際開發中,我們會遇到這麼一種情況:就是並沒有異常發生,但是由於事務結果未滿足具體業務需求,所以我們需要手動回滾事務。於是乎方法也很簡單:

transactionaspectsupport.currenttransactionstatus()

.setrollbackonly();

注意:這是一道經典題。4年前我畢業那會在問,我都工作4年了,現在還問這道。其出現頻率,不亞於 hashmap 的出現頻率!

該問題有很多問法,例如 spring 事務有哪些坑?你用 spring 事務的時候,有遇到過什麼問題麼?其實答案都一樣的。ok,不羅嗦了,開始答案!

我們知道 spring 事務的原理是 aop,進行了切面增強,那麼失效的根本原因是這個 aop 不起作用了。

常見情況有以下幾種:

示例**如下:

@service

public class userservice

@transactional

public void updateuser(user user)

}

此時是無效的。因此上面的**等同於:

@service

public class userservice

@transactional

public void updateuser(user user)

}

此時,這個 this 物件不是**類,而是 userservice 物件本身。

解決方法很簡單,讓那個 this 變成 userservice 的**類即可,就不展開說明了。

@transactional 註解的方法都是被外部其他類呼叫才有效,那麼如果方法修飾符是 private 的,這個方法能被外部其他類調到麼?

既然調不到,事務生效有意義嗎?想通這套邏輯就行了。

記住:@transactional 註解只能應用到 public 方法上。如果你在 protected、private 或者 package-visible 的方法上使用 @transactional 註解,它也不會報錯, 但是這個被註解的方法將不會加入事務之行。

先這麼理解就好了,因為真的去翻原因就要貼**了,這文章可讀性就很差了。

這個問題在第二問講過了,因為預設回滾的是:runtimeexception。如果是其他異常想要回滾,需要在 @transactional 註解上加 rollbackfor 屬性。

又或者是異常被吞了,事務也會失效,這裡不再贅述。

畢竟 spring 事務用的是資料庫的事務,如果資料庫不支援事務,那 spring 事務肯定是無法生效滴。

ok,答到這裡就夠了。

可能有的讀者會說:

煙哥啊,其他文章裡說什麼資料來源沒有配置事務管理器也會導致事務失效,你怎麼沒提?

再比如,你把隔離級別配置成:

@transactional(propagation = propagation.not_supported)

該隔離級別表示不以事務執行,當前若存在事務則掛起,事務肯定不生效啊!這種屬於自己配錯的情況,如果真要舉例,面試官也不愛聽的!在面試中,一句"配置錯誤也會導致事務不生效,例如 *** 配置,舉一兩個即可!"

ok,是一回事!

我們先明確一點,資料庫一般有四種隔離級別,分別為:

read uncommitted:未提交讀;

read committed:提交讀、不可重複讀;

repeatable read:可重複讀;

serializable:可序列化。

而 spring 只是在此基礎上抽象出一種隔離級別 default,表示以資料庫預設配置的為主。例如,mysql 預設的事務隔離級別為 repeatable read,而 oracle 預設隔離級別為read committed。

於是乎,有乙個經典問題是這麼問的:

我資料庫的配置隔離級別是read commited,而spring配置的隔離級別是repeatable read,請問這時隔離級別是以哪乙個為準?

答案是以 spring 配置的為準。jdbc 有乙個介面是這樣的:

意思就是,如果 spring 定義的隔離級別和資料庫的不一樣,則以 spring 定義的為準。

另外,如果 spring 設定的隔離級別資料庫不支援,設定的效果取決於資料庫。

此題考查的是 spring 的事務傳播行為。

我們都知道,預設的傳播行為是 propagation_required。如果外層有事務,則當前事務加入到外層事務,一起提交並一起回滾;如果外層沒有事務,新建乙個事務執行。也就是說,預設情況下只有乙個事務。

當然這種時候如果面試官繼續追問其他傳播行為的情形,該如何回答?

那我們應該把每種傳播機制都拿出來講一遍?沒必要,這種時候直接掀桌子走人。因為你就算背下來了過幾天還是會忘記,用到的時候再去查詢即可。

這道題很多種問法,例如 spring 是如何保證事務獲取的是同乙個 connection?

ok,開始我們的講解。其實答案只有一句話,因為那個 connection 在事務開始時封裝在了 threadlocal 裡,後面事務執行過程中,都是從 threadlocal中 取的。肯定能保證唯一,因為都是在乙個執行緒中執行。

至於**,以j dbctemplate的execute 方法為例,看看下面那張圖就懂了。

面試官 講講 Spring 事務有哪些坑

因為事務這塊,面試的出現機率很高。而大家工作中 crud 的比較多,沒有好好總結過這塊的知識,因此面試容易支支吾吾答不出來。於是乎接下來你就會接到一張好人卡,如 你很優秀,不適合我們公司!主要內容如下 首先,我們先明白 spring 事務的本質其實就是資料庫對事務的支援。沒有資料庫的事務支援,spr...

Spring有哪些優點?

輕量級 spring 在大小和透明性方面絕對屬於輕量級的。控制反轉 ioc spring 使用控制反轉技術實現了松耦合,依賴被注入到物件,而不是建立或尋找依賴物件。面向切面程式設計 aop spring 支援面向切面程式設計,同時應用的業務邏輯與系統的服務分離開來。容器 spring 包含並管理應用...

導致Spring事務失效,常見的情況有哪些

未啟用spring事務管理功能 方法不是public型別的 資料來源未配置事務管理器 自身呼叫問題 異常型別錯誤 異常被吞了 業務和spring事務 必須在乙個執行緒中 1.1 未啟用spring事務管理功能 enabletransactionmanagement 註解用來啟用spring事務自動管...