首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

MyBatis 呼叫預存程序報錯:參數設定異常與空指針的排查思路

     編輯:程式設計綜合問答

現象描述

MyBatis 執行預存程序,資料已成功寫入資料庫,但 Java 端拋出參數設定異常與空指針異常 (NPE)。常見錯誤堆疊:

java.sql.SQLException: Invalid parameter index
    at com.mysql.jdbc.SQLError.createSQLException...
Caused by: java.lang.NullPointerException
    at org.apache.ibatis.type.BaseTypeHandler.setParameter...

核心原因分析

1. OUT/INOUT 參數未正確註冊

MyBatis 對預存程序的 OUT 參數需在 <select> 或 <insert> 中使用 mode="OUT" 並指定 jdbcType,否則驅動程式不知道要註冊哪個索引為輸出參數。

2. 預存程序回傳結果集

若預存程序內有 SELECT 陳述式產生結果集,MyBatis 預設嘗試將結果集映射到 ResultHandler 或 List<T>,但呼叫端若未正確處理 ResultSet 關閉,可能導致連線狀態異常,進而觸發 NPE。

3. 參數順序與數量不匹配

Java 端傳遞的參數個數、順序、類型必須與資料庫端 CREATE PROCEDURE 定義完全一致。多一個、少一個、或 IN/OUT 屬性相反都會導致「Invalid parameter index」。

排查步驟與驗證方法

步驟 1:啟用資料庫端追蹤,確認實際呼叫

  • MySQL: SET GLOBAL general_log = 'ON'; 查看 CALL proc(...) 實際參數。
  • Oracle: 使用 DBMS_MONITOR 或 SQL Trace。
  • SQL Server: SQL Profiler / Extended Events 捕捉 RPC:Completed。

比對資料庫收到的參數個數、順序、類型與 Java 端 Mapper 定義是否一致。

步驟 2:檢查 Mapper XML 參數定義

<select id="callProc" statementType="CALLABLE">
    {CALL my_proc(
        #{param1, mode=IN, jdbcType=VARCHAR},
        #{param2, mode=OUT, jdbcType=INTEGER, javaType=Integer},
        #{param3, mode=INOUT, jdbcType=VARCHAR}
    )}
</select>
  • 所有 OUT/INOUT 參數必須指定 mode 與 jdbcType。
  • javaType 僅在 OUT/INOUT 且需映射到特定包裝類型時需要(如 Integer vs int)。

步驟 3:確認呼叫端參數物件完整性

Map params = new HashMap<>();
params.put("param1", "inputValue");
params.put("param2", null); // OUT 參數必須放入 key,值可為 null
params.put("param3", "inoutValue");
mapper.callProc(params);
// 執行後 params.get("param2") 即為 OUT 回傳值

缺少 key 或 value 為 null 但模式為 IN 會導致 NPE。

步驟 4:簡化測試隔離問題

  1. 在資料庫客戶端手動 CALL proc(...) 驗證程序本身正確。
  2. 用純 JDBC CallableStatement 呼叫,排除 MyBatis 映射層問題。
  3. 逐步加回 MyBatis 映射,定位失敗點。

常見坑點速查表

現象可能原因修正
Invalid parameter index參數個數/順序不匹配、OUT 參數未註冊核對 Mapper XML 與 DB 定義,補齊 mode=OUT
NPE at BaseTypeHandler.setParameterIN 參數值為 null 但 jdbcType 不支援 null補上 jdbcType=NULL 或確保傳非 null 值
資料寫入成功但報錯預存程序有 SELECT 產生結果集未處理Mapper 加 resultSets 或改用 @Options(statementType=CALLABLE) 配合多結果集處理
OUT 參數取不到值呼叫端 Map 缺少對應 key確保 params.put("outParam", null) 存在

總結

MyBatis 呼叫預存程序報「參數設定異常」或 NPE,90% 是OUT/INOUT 參數未正確註冊 mode/jdbcType、參數順序個數不匹配、或呼叫端 Map 缺少 OUT 參數 key。建議先在資料庫端追蹤實際 CALL 陳述式,再對照 Mapper XML 逐項核對,並以純 JDBC 隔離驗證。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved