mybatis-plus中的in的使用,是傳Array?還是傳List?別再糾結了

来源:https://www.cnblogs.com/buguge/archive/2023/07/31/17595281.html
-Advertisement-
Play Games

springboot項目通常配合mybatisplus來做數據CRUD。 我們在查詢或更新數據的時候,有時要用到in來過濾數據。比如SELECT * FROM emax_scbg_order WHERE order_no IN (1305679009380433922,130540525947283 ...


springboot項目通常配合mybatisplus來做數據CRUD。

我們在查詢或更新數據的時候,有時要用到in來過濾數據。比如
SELECT * FROM emax_scbg_order WHERE order_no IN (1305679009380433922,1305405259472830465)


mybatisplus中關於in方法的使用,在傳多個欄位值的時候,我們經常搞不清是傳Array呢還是ArrayList呢?
其實,細心的同學,看一下in方法的定義,就明白了。

 

mybatisplus中有4個in方法的重載。

所有Wrapper的超類是AbstractWrapper,AbstractWrapper實現了Func<Children, R>介面。in方法主要在Func<Children, R>介面中定義。

 

 下麵是Func<Children, R>介面中in方法的4個重載:

//mybatis-plus-core-3.1.2.jar
package com.baomidou.mybatisplus.core.conditions.interfaces;

/**
 * 查詢條件封裝
 *
 * @author hubin miemie HCL
 * @since 2017-05-26
 */
@SuppressWarnings("unchecked")
public interface Func<Children, R> extends Serializable {
    /**
     * ignore
     */
    default Children in(R column, Collection<?> coll) {
        return in(true, column, coll);
    }
    
    /**
     * ignore
     */
    default Children in(R column, Object... values) {
        return in(true, column, values);
    }    

    /**
     * 欄位 IN (v0, v1, ...)
     * <p>例: in("id", 1, 2, 3, 4, 5)</p>
     *
     * <li> 如果動態數組為 empty 則不會進行 sql 拼接 </li>
     *
     * @param condition 執行條件
     * @param column    欄位
     * @param values    數據數組
     * @return children
     */
    default Children in(boolean condition, R column, Object... values) {
        return in(condition, column, Arrays.stream(Optional.ofNullable(values).orElseGet(() -> new Object[]{}))
            .collect(toList()));
    }
    
    /**
     * 欄位 IN (value.get(0), value.get(1), ...)
     * <p>例: in("id", Arrays.asList(1, 2, 3, 4, 5))</p>
     *
     * <li> 如果集合為 empty 則不會進行 sql 拼接 </li>
     *
     * @param condition 執行條件
     * @param column    欄位
     * @param coll      數據集合
     * @return children
     */
    Children in(boolean condition, R column, Collection<?> coll);

}


我們可以看到,in方法接收欄位值的方式,一種是Object...,一種是Collection<?>。
■ Collection<?>不用說了,是集合,比如Listt<E>、Sett<E>、Queuet<E>等。
■ Object...是可變長參數(可變參數),可變長參數本質上就是一個數組,既可以接收一個或多個離散的值,也可以接收數組對象。
也就是說,in方法同時支持傳入數組和集合。取決於你調用哪個重載方法。

 

使用in的姿勢

正確姿勢一(List集合):

List<Long> ids = Arrays.asList(122L,23L);;
new QueryWrapper<Driver>().lambda().in(Driver::getServiceId,ids);

 

正確姿勢二(數組對象):

Long[] ids={1305679009380433922,1305679009380433922};
LambdaQueryWrapper<Driver> queryWrapper = new QueryWrapper<Driver>().lambda().in(Driver::getServiceId,ids);

 

正確姿勢三(離散值):

new QueryWrapper<Driver>().lambda()
.in(Driver::getServiceId,1305679009380433922,1305679009380433922);

 

正確結果:

==>  Preparing: SELECT * FROM emax_scbg_order WHERE order_no IN (?,?)
==> Parameters: 1305679009380433922(String), 1305405259472830465(String)
<==      Total: 2

 

 

千萬別傳模棱兩可的參數,這樣jvm會給你意想不到的結果。

錯誤姿勢一:

.in(
    StringUtils.isNotBlank(vo.getOrderNumList()),
    ScbgOrder::getOrderNo,
    StringUtils.isNotBlank(vo.getOrderNumList()) ? vo.getOrderNumList().split(",") : "");

錯誤結果一:

==> Preparing: SELECT * FROM emax_scbg_order WHERE order_no IN (?)
==> Parameters: [Ljava.lang.String;@3eb6d7a9(String[])
<== Total: 0

調試程式可以看到values里的參數值:

 

 

錯誤姿勢二:

.in(StringUtils.isNotBlank(vo.getOrderNumList()),ScbgOrder::getOrderNo,"123,4566");

 錯誤結果二:

==> Preparing: SELECT * FROM emax_scbg_order WHERE order_no IN (?)
==> Parameters: 1,3(String)
<== Total: 0

 

 

OK,那麼not in怎麼用呢?

在mybatisplus中,not in的用法與in是相同的。如下notIn方法簽名的截圖一看便知:

 

話外:調用in出現NullPointerException,why?

下麵代碼執行到第9行時,拋出空指針異常。可以看出來,這個in重載是public Children in(boolean condition, R column, Object... values)。開發同學疑惑:明明這個in的第一個參數判斷vo.getOprationType()是否為空了呀,為空就不執行後面的第三個參數了,不為空才會執行後面的邏輯呀。那麼,即使vo.getOprationType()為null,也不應該會拋空指針呀!

 1 private LambdaQueryWrapper<PayMerchantOpenFlow> getPayMerchantOpenFlowQueryWrapperByVO(PayMerchantOpenFlowDTO vo){
 2     LambdaQueryWrapper<PayMerchantOpenFlow> wrapper = new QueryWrapper<PayMerchantOpenFlow>().lambda()
 3             .eq(StringUtils.isNotBlank(vo.getMerchantCode()), PayMerchantOpenFlow::getMerchantCode,vo.getMerchantCode())
 4             .eq(null != vo.getRelationId(), PayMerchantOpenFlow::getRelationId,vo.getRelationId())
 5             .eq(StringUtils.isNotBlank(vo.getStatus()), PayMerchantOpenFlow::getStatus,vo.getStatus())
 6             .eq(StringUtils.isNotBlank(vo.getMerchantName()), PayMerchantOpenFlow::getMerchantName,vo.getMerchantName())
 7             .eq(StringUtils.isNotBlank(vo.getPayChannelCode()), PayMerchantOpenFlow::getPayChannelCode,vo.getPayChannelCode())
 8             .eq(StringUtils.isNotBlank(vo.getPayChannelName()), PayMerchantOpenFlow::getPayChannelName,vo.getPayChannelName())
 9             .in(StringUtils.isNotBlank(vo.getOprationType()), PayMerchantOpenFlow::getOprationType,vo.getOprationType().split(","))
10             .between(StringUtils.isNoneBlank(vo.getCreateTimeBegin(), vo.getCreateTimeEnd()), PayMerchantOpenFlow::getCreateTime, vo.getCreateTimeBegin() + " 00:00:01", vo.getCreateTimeEnd() + " 23:59:59")
11             .orderByDesc(PayMerchantOpenFlow::getCreateTime);
12     return wrapper;
13 }

 

答案是:上面的“第一個條件為true時才使用第三個參數執行sql處理”是in方法內部的邏輯,而不是調用方的邏輯。調用方所做的事情是把參數值傳給in方法。所以, 當vo.getOprationType()#split時,由於vo.getOprationType()是null,所以導致了空指針。


當看到一些不好的代碼時,會發現我還算優秀;當看到優秀的代碼時,也才意識到持續學習的重要!--buguge
本文來自博客園,轉載請註明原文鏈接:https://www.cnblogs.com/buguge/p/17595281.html



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • MySQL8_SQL語法 SQL 全稱 Structured Query Language,結構化查詢語言。操作關係型資料庫的編程語言,定義了一套操作關係型資料庫統一標準 。 一、SQL通用語法 在學習具體的SQL語句之前,先來瞭解一下SQL語言的同於語法。 1). SQL語句可以單行或多行書寫,以 ...
  • 複製,即在不同的節點上保存相同的副本,提供數據冗餘。如果一些節點不可用,剩餘的節點仍然可以提供數據服務,這些節點可能部署在不同的地理位置,以此來改善系統性能 ...
  • ### 前言 說到MySQL的MTS,相信很多同學都不陌生,從5.6開始基於schema的並行回放,到5.7的LOGICAL_CLOCK支持基於事務的並行回放,這些內容都有文章講解,在本篇文章不再贅述。今天要講的是,你知道如何查看並行回放是否存在性能瓶頸嗎,是由於主庫事務行為導致無法並行回放,還是由 ...
  • 本文分享自華為雲社區《如何為物聯網設備註入“華為雲+鴻蒙DNA”?看華為雲IoT怎麼答【華為雲IoT +鴻蒙】》,作者: 華為IoT雲服務。 根據市場咨詢機構預測,2025年全球物聯網設備將達到252億個。但各種智能設備大多都有一套自己的系統,而且互相“孤立”,無法交流。鴻蒙的到來,就是要用同一套語 ...
  • 由於Android APP/IOS APP平臺和開發語言的差異,對開髮端和用戶端來說,在系統相容適配、外接藍牙的安裝更新,以及不同平臺之間的移植都有不同程度的制約。 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 介紹 canvas:使用腳本 (通常為 JavaScript) 來繪製圖形的 HTML 元素。 本人遍歷了以下兩份文檔,學習完就相當於有了筆和紙,至於最後能畫出什麼,則需要在 canvas 應用方面進一步學習。 MDN 的 Canvas ...
  • ### 1. 使用箭頭函數簡化函數定義 ```cobol // 傳統函數定義 function add(a, b) { return a + b; } // 箭頭函數簡化 const add = (a, b) => a + b; ``` ### 2. 使用解構賦值簡化變數聲明 ```cobol // ...
  • 1、html的基本結構 a.首先是註釋信息,在html中使用<!--xxx-->這樣的方式來進行註釋 b.DOCTYPE,這是告訴瀏覽器所使用規範,一般可以不加這個,因為現在的瀏覽器預設所使用的規範為html c.head標簽,表示網頁的頭部,其中會放入其他標簽 d.meta標簽,這是一個描述性的標 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...