MyBatis 调用存储过程获取返回值与结果集方案

Owen
Owen
发布时间:2026-10-16 | 6人浏览过
原创

在 Java Web 开发中,经常需要调用数据库存储过程并获取其返回的执行状态或数据。本文将介绍两种基于 MyBatis 的实现方案:一是利用 Map 参数传递获取多个 OUT 返回值;二是直接编写 SQL 逻辑获取查询结果集,适用于无需复杂事务控制的场景。

核心实现思路

MyBatis 处理存储过程主要分为两类需求:

  • 获取标量返回值(IN/OUT):通常需要定义 statementType="CALLABLE",并通过传入的 Map 对象接收 OUT 参数值。
  • 获取数据集或简单输出:可以直接使用 <select> 标签包裹 SQL 语句,类似于普通查询,适合执行后直接返回 List 或单个值的场景。

方案一:通过 Map 接收 OUT 返回值

这是最标准的存储过程调用方式,适用于需要同时传入多个输入参数并获取多个输出状态的场景。

第1步:Mapper 接口定义

在 Mapper 接口中,方法入参定义为 Map<String, Object>,MyBatis 会自动将 OUT 参数写回该 Map 中。

@Select("<![[CDATA[ 
    {call P_CardBindIdCardNo(
        #{name,mode=IN,jdbcType=VARCHAR},
        #{password,mode=IN,jdbcType=VARCHAR},
        #{result,mode=OUT,jdbcType=BIT},
        #{msg,mode=OUT,jdbcType=VARCHAR}
    )} 
]]>")
Object bindCard(Map<String, Object> map) throws Exception;

关键点说明:
- statementType="CALLABLE":部分 XML 配置方式需要显式指定,确保使用 CallableStatement。
- mode=OUT:明确标识哪些参数是存储过程返回给 Java 端的。
- jdbcType:根据实际数据库类型指定,如 BIT、VARCHAR、INT 等。

第2步:Service 层调用

Service 层负责构建参数 Map 并传递给 Mapper。注意异常处理和返回值映射。

@Override
public Object bindCard(Map<String,Object> m) {
    try {
        return cardMapper.bindCard(m);
    } catch (Exception e) {
        e.printStackTrace();
        return new HashMap<String,Object>();
    }
}

第3步:Controller 层提取结果

由于 Map 传值的特点,OUT 参数已经存在于同一个 Map 对象中。调用完成后直接从 Map 中取出对应的 key 即可。

Map<String,Object> m = new HashMap<String,Object>();
m.put("name", "zs");
m.put("password", "55555");
cardservice.bindCard(m);

// 从同一个 Map 中获取存储过程返回的 OUT 参数
JSONObject json = new JSONObject();
json.put("msg", m.get("msg"));
json.put("result", m.get("result"));

方案二:直接执行 SQL 获取结果集

如果存储过程主要用于查询,或者希望避免使用繁琐的 Call 语法,可以直接在 Mapper XML 中使用 <select> 标签包裹 SQL。这种方式更接近普通查询,返回类型为 List 或基本类型。

获取 List<Map> 结果集

适用于存储过程返回多行数据的场景。

// Mapper 接口
List<Map<String, Object>> getAnswerByModulesId(@Param("modulesId") int modulesId, @Param("patientCode") String patientCode) throws Exception;

// Mapper XML
<select id="getAnswerByModulesId" resultType="map" statementType="CALLABLE">
    EXEC getAnswerByModulesId #{modulesId},#{patientCode}
</select>

获取单值返回值(Output 变量提取)

如果不想用 Call 语法但又想获取一个 Output 变量,可以在 SQL 中声明局部变量并使用 SELECT 语句将其作为结果集返回。

<select id="getUpdateHumanDisease" resultType="java.lang.String">
    declare @result varchar(50)
    exec updateHumanDisease #{0},#{1},#{2},@result output
    select @result
</select>

此写法利用了 SQL Server 的特性,通过 SELECT 将变量值作为查询结果返回,MyBatis 可正常映射为 String 类型。

注意事项与常见问题

多数据源切换限制

在使用动态数据源切换时,如果调用存储过程涉及跨库操作或需要在事务中切换数据源,务必注意:

调用存储过程时不能开启事务,否则可能导致无法切换数据源连接。建议在 Service 层关闭当前事务或单独管理连接上下文。

参数绑定细节

  • 对于 OUT 参数,即使 Java 端未赋值,只要 Map 中存在该 Key,MyBatis 会在执行后填充值。
  • 若遇到乱码问题,检查 JDBC URL 中的 characterEncoding 设置,以及存储过程内部的 NCHAR/NVARCHAR 类型匹配。
  • 不同数据库方言(MySQL, Oracle, SQL Server)对 OUT 参数的支持程度略有差异,Oracle 通常要求明确指定 mode,而 MySQL 可能因驱动版本不同表现不一致。

总结

MyBatis 调用存储过程的核心在于正确配置 statementType 和参数模式。对于复杂的 I/O 交互,推荐使用 Map 封装参数以实现解耦;对于简单查询或单值输出,可直接利用 SQL 结构简化调用流程。在实际项目中,需特别关注事务管理与数据源连接的兼容性,以确保系统稳定性。

以上就是 MyBatis 调用存储过程获取返回值与结果集的详细内容,更多关于 MyBatis 高级用法及数据库交互的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表