You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+MyBatis调用MySQL存储过程报错:参数3不是OUT参数

解决MyBatis调用MySQL存储过程时「Parameter number 3 is not an OUT parameter」错误

我之前也踩过这个坑,咱们来一步步捋清楚问题出在哪,再给出靠谱的修复方案。

问题根源

你当前的写法里,MyBatis没办法正确识别存储过程的OUT参数——你的Mapper接口直接返回Result对象,但MyBatis需要一个明确的载体来绑定OUT参数的值。现在XML映射里写的#{out0,mode=OUT,jdbcType=INTEGER},这个out0没有对应的入参对象属性,MyBatis会默认把它当成IN参数处理,这就和存储过程定义的OUT参数冲突,直接抛出了那个错误。

另外还有个小问题:你的测试代码里直接new testDao()是错误的!MyBatis的Mapper接口是动态生成代理类的,必须通过Spring容器或者SqlSession获取实例,不能直接实例化接口。

修复方案

方案1:用Map作为参数与结果载体(最简单直接)

这种方式不需要修改实体类,用Map传递IN参数并接收OUT参数:

  • 修改Mapper接口:
public interface TestDao {
    void testSP(Map<String, Object> params);
}
  • 修改XML映射文件:
<select id="testSP" statementType="CALLABLE">
    {call testSP(
        #{id, mode=IN, jdbcType=VARCHAR},
        #{name, mode=IN, jdbcType=VARCHAR},
        #{out0, mode=OUT, jdbcType=INTEGER},
        #{out1, mode=OUT, jdbcType=INTEGER}
    )}
</select>
  • 修正后的测试代码:
// 从Spring容器获取Dao实例,不要直接new
TestDao testDao = applicationContext.getBean(TestDao.class);
Map<String, Object> params = new HashMap<>();
params.put("id", "testid");
params.put("name", "testname");
testDao.testSP(params);
// 从Map中取出OUT参数结果
System.out.println(params.get("out0"));
System.out.println(params.get("out1"));

方案2:用实体类作为参数载体(更贴合业务场景)

如果你还是想用Result类接收结果,可以把它作为入参传递给Mapper方法:

  • 修改Mapper接口:
public interface TestDao {
    void testSP(@Param("id") String id, @Param("name") String name, @Param("result") Result result);
}
  • 修改XML映射文件:
<select id="testSP" statementType="CALLABLE">
    {call testSP(
        #{id, mode=IN, jdbcType=VARCHAR},
        #{name, mode=IN, jdbcType=VARCHAR},
        #{result.out0, mode=OUT, jdbcType=INTEGER},
        #{result.out1, mode=OUT, jdbcType=INTEGER}
    )}
</select>
  • 修正后的测试代码:
TestDao testDao = applicationContext.getBean(TestDao.class);
Result result = new Result();
testDao.testSP("testid", "testname", result);
System.out.println(result.getOut0());
System.out.println(result.getOut1());

方案3:用注解简化配置(无需XML)

如果不想写XML,直接用MyBatis注解实现:

  • 修改Mapper接口:
public interface TestDao {
    @Select("{call testSP(#{id, mode=IN, jdbcType=VARCHAR}, #{name, mode=IN, jdbcType=VARCHAR}, #{out0, mode=OUT, jdbcType=INTEGER}, #{out1, mode=OUT, jdbcType=INTEGER})}")
    @Options(statementType = StatementType.CALLABLE)
    void testSP(Map<String, Object> params);
}

测试代码和方案1一致即可。

额外提醒

  1. 命名规范:Java里类名、接口名要遵循大驼峰(比如TestDao、Result),变量名用小驼峰,这能避免很多潜在的语法或框架识别问题。
  2. 参数类型匹配:你存储过程的IN参数是TEXT类型,MyBatis里用jdbcType=VARCHAR没问题,如果是超长文本可以改成jdbcType=LONGVARCHAR。

内容的提问来源于stack exchange,提问作者H.Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:22:03