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

2021-10-10 14:24:38 字數 3634 閱讀 5386

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

主要內容如下:

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

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

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

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

執行 crud;

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

關閉連線 conn.close()。

首先我們要明白, 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 不起作用了。

常見情況有以下幾種:

3.1 發生自呼叫

@service

public class userservice

@transactional

public void updateuser(user user)

}

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

@service

public class userservice

@transactional

public void updateuser(user user)

}

此時,這個 this 物件不是**類,而是 userservice 物件本身。解決方法很簡單,讓那個 this 變成 userservice 的**類即可,就不展開說明了。

3.2 方法修飾符不是 public

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

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

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

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

3.3 發生了錯誤的異常

這個問題在第二問講過了,因為預設回滾的是:runtimeexception。如果是其他異常想要回滾,需要在 @transactional 註解上加 rollbackfor 屬性。又或者是異常被吞了,事務也會失效,這裡不再贅述。

3.4 資料庫不支援事務

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

ok,答到這裡就夠了。

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

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

ok,是一回事!

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

而 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事務失效的八大原因,吊打面試官

1 資料庫引擎不支援事務 2 沒有被 spring 管理 3 方法不是 public 的 4 自身呼叫問題 5 資料來源沒有配置事務管理器 6 不支援事務 7 異常被吃了 8 異常型別錯誤 總結這裡以 mysql 為例,其 myisam 引擎是不支援事務操作的,innodb 才是支援事務的引擎,一般...

面試官 說說資料庫事務吧

面試官在資料庫這方面最常問的除了sql優化,還有資料庫事務 儲存引擎等相關知識。上期有人說沒有自動門,所以這一期我特地造了自動門,這門沒有四五塊造不下來。注意 只是crud的搬磚工就不需要看了,看了也忘了,只需要拉到最後,點讚 在看 分享,一鍵三連然後收藏起來就行了。事務是指是程式中一系列嚴密的邏輯...