日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

盤點 Mybatis 使用過程中遇到的坑!

來源: 責編: 時間:2024-09-10 09:47:53 143觀看
導讀01、引言大家好,我是了不起,前一段時間在工作中因為一個疏忽踩了一個坑,最終通過異常棧追溯源碼解決了問題。下面我來給大家還原一下案發(fā)現場,并介紹一下自己的解決思路,希望能對大家有所啟發(fā)。02、案發(fā)現場當時的業(yè)務邏輯

01、引言

大家好,我是了不起,前一段時間在工作中因為一個疏忽踩了一個坑,最終通過異常棧追溯源碼解決了問題。RiO28資訊網——每日最新資訊28at.com

下面我來給大家還原一下案發(fā)現場,并介紹一下自己的解決思路,希望能對大家有所啟發(fā)。RiO28資訊網——每日最新資訊28at.com

02、案發(fā)現場

當時的業(yè)務邏輯主要通過 Mybatis 框架來修改數據,具體示例如下:RiO28資訊網——每日最新資訊28at.com

import org.springframework.data.repository.query.Param;public interface GroupMapper {  int updateGroup(@Param("oldSerial") Set<Integer> oldSerial, @Param("newSerial") int newSerial); int invalidGroup(@Param("set") Set<Integer> set);}
<update id="updateGroup">    update groupCode_table_use    set groupCode=#{newSerial}    where groupCode in    <foreach collection="oldSerial" close=")" open="(" item="item" separator=",">        #{item}    </foreach></update><update id="invalidGroup">    update groupCode_table    set status='無效'    where groupCode in    <foreach collection="set" close=")" open="(" item="item" separator=",">        #{item}    </foreach></update>

本以為 so easy 的代碼,出現意外了!第一個sql語句updateGroup正常運行,第二個sql語句invalidGroup竟然報錯了???RiO28資訊網——每日最新資訊28at.com

報錯信息如下:RiO28資訊網——每日最新資訊28at.com

圖片圖片RiO28資訊網——每日最新資訊28at.com

從日志上可以看出,提示set參數找不到!RiO28資訊網——每日最新資訊28at.com

明明使用了@Param("set")將參數命名為set為何找不到,完全不符合多年開發(fā)的認知。RiO28資訊網——每日最新資訊28at.com

更加詭異的是updateGroup已使用了同樣的方式去遍歷,完全沒得問題,那么問題出現在了哪了?RiO28資訊網——每日最新資訊28at.com

小伙伴可以先猜一猜!RiO28資訊網——每日最新資訊28at.com

03、原因分析

百思不得其解下,我掏出了祖?zhèn)鹘^活 debug 源碼,最終發(fā)現原來是Mybatis對集合Set進行了特殊處理。RiO28資訊網——每日最新資訊28at.com

案發(fā)項目引入的Mybatis版本是 3.5.1。部分源碼如下!RiO28資訊網——每日最新資訊28at.com

org.apache.ibatis.session.defaults.DefaultSqlSession.java@Overridepublic int update(String statement, Object parameter) {  try {    dirty = true;    MappedStatement ms = configuration.getMappedStatement(statement);    //調用了wrapCollection方法對參數進行了處理    return executor.update(ms, wrapCollection(parameter));  } catch (Exception e) {    throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);  } finally {    ErrorContext.instance().reset();  }}/*** 如果參數實現了Collection接口或是數組類型 wrapCollection方法會對參數進行封裝* 如果參數實現了Collection接口會封裝為含collection鍵的Map*     如果參數又實現了List接口會封裝為含list鍵的Map(追增)*     對Set集合沒有特殊處理* 如果參數是數組類型會封裝為含array鍵的Map*/private Object wrapCollection(final Object object) {  if (object instanceof Collection) {    StrictMap<Object> map = new StrictMap<>();    map.put("collection", object);    if (object instanceof List) {      map.put("list", object);    }    return map;  } else if (object != null && object.getClass().isArray()) {    StrictMap<Object> map = new StrictMap<>();    map.put("array", object);    return map;  }  return object;}

通過以上的源碼分析,發(fā)現Mybatis框架對集合參數進行了特殊處理。RiO28資訊網——每日最新資訊28at.com

這就是為什么報錯信息中提示Available parameters are [collection]。RiO28資訊網——每日最新資訊28at.com

找到了collection錯誤信息從哪里來問題,接下來我們分析一下set參數到了哪里去。RiO28資訊網——每日最新資訊28at.com

首先updateGroup可以正常執(zhí)行是因為源碼中對集合的特殊處理只對單參數生效,也就是說@Param("set")注解失效是因為被Mybatis自家的特殊處理給覆蓋了?RiO28資訊網——每日最新資訊28at.com

這不合乎常理啊,那么問題可能出在@Param注解身上,通過排查代碼發(fā)現GroupMapper.java類引用的@Param注解不對!RiO28資訊網——每日最新資訊28at.com

// 代碼引入的注解類Paramimport org.springframework.data.repository.query.Param;// 期望的注解類,應該由mybatis提供import org.apache.ibatis.annotations.Param;

實際上,springframework包下的@Param注解執(zhí)行時機在wrapCollection處理之前,wrapCollection對集合的特殊處理將springframework包下的@Param注解處理覆蓋掉了,所以無法解析參數set。而mybatis包下的@Param注解執(zhí)行時機在wrapCollection處理之后,程序可以正常運行。RiO28資訊網——每日最新資訊28at.com

最終確定,繞了這么大一圈,原來是包導入錯了,誰能想到springframework包下還有一個@Param注解,在多參數的情況下竟然可以正常使用o(╥﹏╥)o。RiO28資訊網——每日最新資訊28at.com

04、異常棧分析法

整個異常排查過程中,主要通過分析異常棧信息進行快速定位。下面我給大家介紹一下異常棧分析法。RiO28資訊網——每日最新資訊28at.com

我們在工作中查看異常棧,往往都是業(yè)務代碼異常導致的,這個時候我們只需要關心是在我們編寫的哪段代碼中出了問題。RiO28資訊網——每日最新資訊28at.com

而這時好用的idea也會為溫馨的為我們做出提示,會在異常棧中將我們編寫的方法位置信息標藍處理,這樣我們就定快速定位出現問題的代碼。RiO28資訊網——每日最新資訊28at.com

圖片圖片RiO28資訊網——每日最新資訊28at.com

但是一旦是底層引用的jar包出現了異常,僅僅是這樣查看異常棧是不夠的。下面我們就以上面案例中的異常棧來帶大家分析。RiO28資訊網——每日最新資訊28at.com

當前異常:RiO28資訊網——每日最新資訊28at.com

圖片圖片RiO28資訊網——每日最新資訊28at.com

原始異常:RiO28資訊網——每日最新資訊28at.com

圖片圖片RiO28資訊網——每日最新資訊28at.com

分析流程:RiO28資訊網——每日最新資訊28at.com

  • 異常調用棧順序:從上至下為方法調用順序的逆序,異常由異常棧的最上面的方法拋出,整個調用的入口在最下方。
  • 尋找原始異常入口技巧:檢索異常棧中與原始異常入口(最下面)拋出位置同名的方法。
  • 尋找真正異常出現的位置,要找最后一個 Caused by 的第一行棧幀。


RiO28資訊網——每日最新資訊28at.com

"Caused by" 是 Java 異常處理機制中的一部分,它表示當前異常是由另一個異常引起的。在 Java 中,每個 Throwable 對象都可以通過 getCause() 方法獲取到原始異常,這個原始異常就是通過 "Caused by" 打印出來的。RiO28資訊網——每日最新資訊28at.com

異常棧示例代碼:

假設你在catch塊中捕獲了一個異常,并重新拋出了一個新的異常,同時保留了原始異常的信息:RiO28資訊網——每日最新資訊28at.com

public class Example {    public static void main(String[] args) {        try {            methodThatThrowsException();        } catch (Exception e) {            throw new RuntimeException("Caught an exception", e);        }    }    public static void methodThatThrowsException() throws Exception {        throw new Exception("Original exception");    }}

當你運行上述代碼時,控制臺輸出的異常棧信息通常會包含Caused by信息:RiO28資訊網——每日最新資訊28at.com

java.lang.RuntimeException: Caught an exception    at Example.main(Example.java:7)Caused by: java.lang.Exception: Original exception    at Example.methodThatThrowsException(Example.java:12)    at Example.main(Example.java:5)
  • java.lang.Exception: Original exception 是原始異常。
  • java.lang.RuntimeException: Caught an exception 是新拋出的異常,并且包含了原始異常作為其原因。
  • Caused by 信息顯示了原始異常的詳細信息,這有助于調試和理解異常的來源。

如何保留原始異常信息呢?RiO28資訊網——每日最新資訊28at.com

  • 方式一:直接傳遞原始異常:
try {     methodThatThrowsException(); } catch (Exception e) {     throw new RuntimeException("Caught an exception", e); }
  • 方式二:使用 addSuppressed 方法:
try {     methodThatThrowsException(); } catch (Exception e) {     RuntimeException newException = new RuntimeException("Caught an exception");     newException.addSuppressed(e);     throw newException; }

05、結語

學會查看分析異常棧,可以為我們工作大大提高效率,希望這篇文章給大家?guī)硎斋@,最后再送給大家一個小技巧。異常棧不僅僅可以用來排查異常哦,還可以幫助大家學習源碼,debug 源碼找不到入口怎么辦,那就創(chuàng)造一個異常!RiO28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-112730-0.html盤點 Mybatis 使用過程中遇到的坑!

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: SpringBoot與XXL-JOB高效定時任務管理指南

下一篇: Elasticsearch 使用誤區(qū)—單次請求獲取大量數據

標簽:
  • 熱門焦點
  • 紅魔電競平板評測:大屏幕硬實力

    前言:三年的疫情因為要上網課的原因激活了平板市場,如今網課的時代已經過去,大家的生活都恢復到了正軌,這也就意味著,真正考驗平板電腦生存的環(huán)境來了。也就是面對著這種殘酷的
  • 28個SpringBoot項目中常用注解,日常開發(fā)、求職面試不再懵圈

    前言在使用SpringBoot開發(fā)中或者在求職面試中都會使用到很多注解或者問到注解相關的知識。本文主要對一些常用的注解進行了總結,同時也會舉出具體例子,供大家學習和參考。注解
  • 摸魚心法第一章——和配置文件說拜拜

    為了能摸魚我們團隊做了容器化,但是帶來的問題是服務配置文件很麻煩,然后大家在群里進行了“親切友好”的溝通圖片圖片圖片圖片對比就對比,簡單對比下獨立配置中心和k8s作為配
  • 2023 年的 Node.js 生態(tài)系統

    隨著技術的不斷演進和創(chuàng)新,Node.js 在 2023 年達到了一個新的高度。Node.js 擁有一個龐大的生態(tài)系統,可以幫助開發(fā)人員更快地實現復雜的應用。本文就來看看 Node.js 最新的生
  • 一文看懂為蘋果Vision Pro開發(fā)應用程序

    譯者 | 布加迪審校 | 重樓蘋果的Vision Pro是一款混合現實(MR)頭戴設備。Vision Pro結合了虛擬現實(VR)和增強現實(AR)的沉浸感。其高分辨率顯示屏、先進的傳感器和強大的處理能力
  • 一文搞定Java NIO,以及各種奇葩流

    大家好,我是哪吒。很多朋友問我,如何才能學好IO流,對各種流的概念,云里霧里的,不求甚解。用到的時候,現百度,功能雖然實現了,但是為什么用這個?不知道。更別說效率問題了~下次再遇到,
  • 拼多多APP上線本地生活入口,群雄逐鹿萬億市場

    Tech星球(微信ID:tech618)文 | 陳橋輝 Tech星球獨家獲悉,拼多多在其APP內上線了&ldquo;本地生活&rdquo;入口,位置較深,位于首頁的&ldquo;充值中心&rdquo;內,目前主要售賣美食相關的
  • 本地生活這塊肥肉,拼多多也想吃一口

    出品/壹覽商業(yè) 作者/李彥編輯/木魚拼多多也看上本地生活這塊蛋糕了。近期,拼多多在App首頁&ldquo;充值中心&rdquo;入口上線了本機生活界面。壹覽商業(yè)發(fā)現,該界面目前主要
  • Windows 11發(fā)布,微軟一改往常對老機型開放的態(tài)度

    距離 Windows 11 發(fā)布已經過去一周,在過去一周里,很多數碼愛好者圍繞其對 Android 應用的支持、對老機型的升級問題展開了激烈討論。與以往不同的是,在這次大
Top 主站蜘蛛池模板: 江津市| 潞城市| 三原县| 翁牛特旗| 金塔县| 丹凤县| 彭州市| 洪雅县| 高安市| 文山县| 思南县| 上蔡县| 阿拉尔市| 靖安县| 封丘县| 奉节县| 鹤山市| 兴隆县| 安泽县| 泰安市| 凭祥市| 冷水江市| 英德市| 万盛区| 平顶山市| 和龙市| 四会市| 黑山县| 东城区| 陕西省| 修武县| 古浪县| 自治县| 禄劝| 会理县| 怀远县| 赤水市| 昌吉市| 杭锦旗| 新野县| 牟定县|