最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MybatisPlus字段自動(dòng)填充失效,填充值為null的解決方案

 更新時(shí)間:2024年01月13日 09:23:36   作者:庸人沖  
這篇文章主要介紹了MybatisPlus字段自動(dòng)填充失效,填充值為null的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

問題描述

有一個(gè)實(shí)體類UserEntity 對(duì)其屬性 UserEntity#createTime 字段注解了 @TableField(fill = FieldFill.INSERT)

image-20220521091544321

根據(jù)業(yè)務(wù)需要定義了 UserMapper#inserUser() 方法,參數(shù)注解了 @Param(“user”) 如下:

image-20220521091425353

當(dāng)調(diào)用該方法時(shí),無法給 createTime 字段自動(dòng)填充值,報(bào)錯(cuò)信息如下:

### Cause: java.sql.SQLIntegrityConstraintViolationException: Column 'create_time' cannot be null<LF>; Column 'create_time' cannot be null; nested exception is java.sql.SQLIntegrityConstraintViolationException: Column 'create_time' cannot be null]

問題剖析

在檢查了 MetaObjectHandler 實(shí)現(xiàn)類的重寫的方法無誤后,開始嘗試跟蹤 Mybatis-plus 的源碼。

發(fā)現(xiàn)在 MybatisParameterHandler#process() 中完成了自動(dòng)填充的功能,在自動(dòng)填充前需要先獲取 tableInfo 信息:

image-20220521093717931

而這個(gè) TableInfoHelper.getTableInfo() 方法只有當(dāng)傳入的 Class 對(duì)象是實(shí)體類對(duì)象時(shí)才能獲取到 tableInfo :

image-20220521094104208

那么問題來了,我的參數(shù)確實(shí)是實(shí)體類,但是為什么獲取不到 TableInfo 呢?

因?yàn)?MybatisParameterHandler#process() 方法的 parameter 參數(shù)在調(diào)用我自定義的方法時(shí),傳入的是一個(gè) Map ,這個(gè) Mapkey 是一個(gè)字符串表示,而 value 是我自定義方法的參數(shù)實(shí)例,可以看到下圖中我的 Map 有兩個(gè) Entry 一個(gè) key=user 一個(gè) key=param1

image-20220521094353846

而最為重要的是,在這個(gè) process() 方法中,如果傳入的是一個(gè) Map,Mybatis-plus 會(huì)從其中取 key="et" 的值,這就是問題的原因所在!??!

image-20220521094759755

而傳入的這個(gè) Map 不存在 key="et" 的映射關(guān)系。因此兩個(gè) TableInfoHelper.getTableInfo() 方法都進(jìn)不去,所以也就不會(huì)進(jìn)行自動(dòng)填充。

image-20220521095247096

那么如何建立 "et" -> entity 的映射關(guān)系呢?我們Map中原本的兩個(gè)的映射關(guān)系又是從哪里來的?

根據(jù)方法的調(diào)用鏈,一直回退到 Mybatis 框架中的 MapperMethod#execute() 方法中的一行代碼:

image-20220521095621950

上面的 convertArgsToSqlCommandParam() 方法就是通過我們方法的實(shí)際參數(shù) args 轉(zhuǎn)換為執(zhí)行 sql 語(yǔ)句需要的參數(shù)格式,而返回值 param 就是之前傳入的那個(gè) map。

我們跟蹤該方法的調(diào)用鏈,發(fā)現(xiàn)最終調(diào)用了 ParamNameResolver#getNamedParams() 方法,該方法有3個(gè)分支,決定了我們最終得到參數(shù)是怎樣的,源碼如下:

  public Object getNamedParams(Object[] args) {
    final int paramCount = names.size();
     // 1. 方法是空參時(shí)直接返回
    if (args == null || paramCount == 0) {  
      return null;
    } else if (!hasParamAnnotation && paramCount == 1) { 
       // 2. 方法的參數(shù)沒有注解 @Param 并且只有一個(gè)參數(shù)時(shí),直接返回這個(gè)參數(shù)實(shí)例
      Object value = args[names.firstKey()];
      return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
    } else {
        // 3. 否則,就建立映射關(guān)系(要么注解了 @Param,要么就是多個(gè)參數(shù))
      final Map<String, Object> param = new ParamMap<>();
      int i = 0;
        // 遍歷  names 中每一個(gè) entry, 這個(gè) names 是一個(gè) sortedMap,該 Map 會(huì)保存方法參數(shù)的索引 -> 參數(shù)名稱的映射關(guān)系,如果參數(shù)注解了 @Param,則值時(shí) @Param("xxx") 中的 xxx,如果沒有注解 @Param 則值也為參數(shù)索引,例如:
        // aMethod(@Param("M") int a, @Param("N") int b) -> {{0, "M"}, {1, "N"}}
		// aMethod(int a, int b) -> {{0, "0"}, {1, "1"}}
      for (Map.Entry<Integer, String> entry : names.entrySet()) {
          // key = 參數(shù)名稱(@Param("xxx"))或 參數(shù)的索引
          // value = 參數(shù)實(shí)例
        param.put(entry.getValue(), args[entry.getKey()]);
        
         // add generic param names (param1, param2, ...)
         // 下面就是添加 "paramN" -> 參數(shù)實(shí)例的映射,我們知道在 mapper 文件中可以使用 #{paramN} 來獲取參數(shù)列表的值,這就是原因。
        final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
        // ensure not to overwrite parameter named with @Param
        if (!names.containsValue(genericParamName)) {
          param.put(genericParamName, args[entry.getKey()]);
        }
        i++;
      }
      return param;
    }
  }

那么顯然,本次調(diào)用返回的 param 如下:

image-20220521101650953

解決方法

通過上面的分析,我們就知道了為什么咱們傳給 MybatisParameterHandler#process() 的參數(shù)是一個(gè) Map,并且也知道了為什么自動(dòng)填充失敗的根本原因,那么解決方法也就很明確了:

給實(shí)體類參數(shù)注解為 @Param(“et”),修改后記得 Mapper 文件中占位符中也要改成 #{et.property}

image-20220521102147149

或者方法只有一個(gè)實(shí)體類參數(shù)時(shí)就別標(biāo)注 @Param 注解了,這樣返回的就是實(shí)體類的實(shí)例而不是一個(gè) Map,同樣記得 Mapper 文件中占位符直接寫屬性 #{property} 即可。

image-20220521103258068

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Springboot集成Jasypt實(shí)現(xiàn)配置文件加密的方法

    Springboot集成Jasypt實(shí)現(xiàn)配置文件加密的方法

    Jasypt是一個(gè)java庫(kù),它允許開發(fā)員以最少的努力為他/她的項(xiàng)目添加基本的加密功能,并且不需要對(duì)加密工作原理有深入的了解,這篇文章主要介紹了Springboot集成Jasypt實(shí)現(xiàn)配置文件加密,需要的朋友可以參考下
    2023-04-04
  • Java動(dòng)態(tài)循環(huán)隊(duì)列是如何實(shí)現(xiàn)的

    Java動(dòng)態(tài)循環(huán)隊(duì)列是如何實(shí)現(xiàn)的

    今天帶大家學(xué)習(xí)java隊(duì)列的相關(guān)知識(shí),文章圍繞著如何實(shí)現(xiàn)Java動(dòng)態(tài)循環(huán)隊(duì)列展開,文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • 不了解這12個(gè)語(yǔ)法糖,別說你會(huì)Java

    不了解這12個(gè)語(yǔ)法糖,別說你會(huì)Java

    這篇文章主要介紹了不了解這12個(gè)語(yǔ)法糖,別說你會(huì)Java,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • 深入理解Spring Cloud Zuul過濾器

    深入理解Spring Cloud Zuul過濾器

    這篇文章主要給大家介紹了關(guān)于Spring Cloud Zuul過濾器的相關(guān)資料,通過閱讀本文您將了解:Zuul過濾器類型與請(qǐng)求生命周期、如何編寫Zuul過濾器、如何禁用Zuul過濾器和Spring Cloud為Zuul編寫的過濾器及其功能,需要的朋友可以參考下。
    2017-02-02
  • 解決Spring國(guó)際化文案占位符失效問題的方法

    解決Spring國(guó)際化文案占位符失效問題的方法

    本篇文章主要介紹了解決Spring國(guó)際化文案占位符失效問題的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • Java手寫線程池的實(shí)現(xiàn)方法

    Java手寫線程池的實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了Java手寫線程池的實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢和刪除商品類別功能實(shí)現(xiàn)

    SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢和刪除商品類別功能實(shí)現(xiàn)

    SSH框架網(wǎng)上商城項(xiàng)目第8戰(zhàn)之查詢和刪除商品類別功能實(shí)現(xiàn),為項(xiàng)目增加功能,添加、更新、刪除和查詢操作,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Java用遞歸方法解決漢諾塔問題詳解

    Java用遞歸方法解決漢諾塔問題詳解

    漢諾塔問題是一個(gè)經(jīng)典的問題。漢諾塔(Hanoi?Tower),又稱河內(nèi)塔,源于印度一個(gè)古老傳說。本文將用Java遞歸方法求解這一問題,感興趣的可以學(xué)習(xí)一下
    2022-04-04
  • java通過DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)

    java通過DelayQueue實(shí)現(xiàn)延時(shí)任務(wù)

    本文主要介紹了java通過DelayQueue實(shí)現(xiàn)延時(shí)任務(wù),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Jackson自定義序列化與反序列化注解詳解

    Jackson自定義序列化與反序列化注解詳解

    這篇文章主要介紹了Jackson自定義序列化與反序列化注解詳解,某些場(chǎng)景下,我們使用Jackson對(duì)數(shù)據(jù)進(jìn)行序列化或反序列化的時(shí)候,需要對(duì)某些數(shù)據(jù)進(jìn)行特殊處理,需要的朋友可以參考下
    2023-11-11

最新評(píng)論

武鸣县| 岳普湖县| 宁海县| 洛川县| 高清| 肥城市| 大足县| 神池县| 嵊州市| 钦州市| 洛川县| 泸定县| 大同市| 宜黄县| 平阴县| 合肥市| 武隆县| 沂水县| 开封县| 双江| 清丰县| 桓台县| 梨树县| 达州市| 周口市| 弋阳县| 永昌县| 高青县| 周至县| 双流县| 南和县| 麟游县| 岱山县| 金沙县| 渑池县| 宁强县| 丰城市| 宝坻区| 凤凰县| 五大连池市| 青铜峡市|