因為事務這塊,面試的出現機率很高。而大家工作中 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的搬磚工就不需要看了,看了也忘了,只需要拉到最後,點讚 在看 分享,一鍵三連然後收藏起來就行了。事務是指是程式中一系列嚴密的邏輯...