mybatis调用存储过程需用或标签配{call...}语法并设statementtype="callable",正确配置in/out/inout参数模式及jdbctype,out参数值从入参map中获取而非返回值。

MyBatis 调用存储过程主要通过 <select></select>、<update></update> 或 <procedure></procedure> 标签(推荐用 <select></select> 或 <update></update>,因 MyBatis 无原生 <procedure></procedure> 标签)配合 {call ...} 语法实现,关键在于正确配置参数模式(IN、OUT、INOUT)和结果映射。
1. 存储过程示例(以 MySQL 为例)
假设有一个带输入参数、输出参数和结果集的存储过程:
DELIMITER $$
CREATE PROCEDURE GetUserByIdAndCount(
IN p_user_id INT,
OUT p_total_count INT
)
BEGIN
SELECT * FROM user WHERE id = p_user_id;
SELECT COUNT(*) INTO p_total_count FROM user;
END$$
DELIMITER ;
2. Mapper 接口定义
定义一个接口方法,接收输入参数并接收输出参数(需用 Map 或自定义对象封装):
public interface UserMapper {
// 使用 Map 传参,支持 IN/OUT 参数
void getUserByIdAndCount(Map<string object> params);
}</string>
3. Mapper XML 配置(关键!)
使用 <select></select> 标签调用存储过程,statementType="CALLABLE" 必须设置;参数用 #{paramName, mode=MODE} 指定方向:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
<select id="getUserByIdAndCount" statementtype="CALLABLE" resulttype="User">
{CALL GetUserByIdAndCount(
#{userId, mode=IN, jdbcType=INTEGER},
#{totalCount, mode=OUT, jdbcType=INTEGER}
)}
</select>
- mode=IN:输入参数,Java 传入值,数据库读取
- mode=OUT:输出参数,数据库写入,Java 通过 Map 获取返回值
- mode=INOUT:双向参数,Java 先传值,数据库可修改后回传
- jdbcType 建议显式指定,避免空值或类型推断错误
- 若存储过程只返回结果集(无 OUT 参数),
resultType或resultMap用于映射查询结果
4. Java 调用方式
将参数放入 Map,调用方法后从 Map 中取出 OUT 参数值:
Map<string object> params = new HashMap();
params.put("userId", 123);
userMapper.getUserByIdAndCount(params);
<p>// 获取输出参数
Integer totalCount = (Integer) params.get("totalCount");
List<user> users = (List<user>) params.get("RETURN_VALUE"); // 注意:部分驱动可能将结果集也存为 RETURN_VALUE,但更推荐用 resultType 显式映射</user></user></p></string>
⚠️ 注意:MyBatis 默认将第一个结果集自动映射为方法返回值(若 XML 中有 resultType),而 OUT 参数需从入参 Map 中提取。如果存储过程返回多个结果集,需开启 multipleResultSetsEnabled=true(MyBatis 配置),并用 <resultmap></resultmap> 的 <collection></collection> 或多结果集映射处理。
5. Oracle 特别说明
Oracle 存储过程若返回游标(REF CURSOR),需在 XML 中声明 jdbcType=ORACLECURSOR,并用 resultMap 映射:
<select id="getUsersByDept" statementtype="CALLABLE" resultmap="userResultMap">
{CALL GET_USERS_BY_DEPT(
#{deptId, mode=IN, jdbcType=NUMERIC},
#{userCursor, mode=OUT, jdbcType=ORACLECURSOR, resultMap=userResultMap}
)}
</select>
不复杂但容易忽略细节:参数 mode 必须准确、jdbcType 尽量显式、OUT 参数值只能从传入的 Map 中取,而不是方法返回值。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










