MyBatis 调用存储过程获取返回值与结果集方案
在 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 高级用法及数据库交互的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













