全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-20 分钟 ✍️ juanwangdev

输入输出参数

预计阅读时间: 约 8 分钟

存储过程的核心优势在于双向数据交互:既可以向数据库传入计算参数,又能将处理结果通过输出参数返回。MyBatis 提供了完善的参数模式支持,通过 mode 属性精确控制每个参数的数据流向。

一、IN / OUT / INOUT 参数详解

1.1 三种参数模式

模式方向说明典型场景
INJava → DB传入参数值,存储过程只读查询条件、过滤参数
OUTDB → Java存储过程写入,Java 读取结果统计值、返回码、错误信息
INOUT双向传入初始值,存储过程修改后返回累加器、分页游标

1.2 IN 参数(输入)

最常见的参数模式,等同于普通查询参数:

XML
<select id="getUserCountByDept" statementType="CALLABLE">
    {call get_user_count(
        #{deptId, mode=IN, jdbcType=INTEGER}
    )}
</select>

1.3 OUT 参数(输出)

需要配合 Map 或 JavaBean 传递,调用后从参数对象中获取结果:

XML
<select id="calcOrderTotal" statementType="CALLABLE" parameterType="map">
    {calc_order_total(
        #{customerId, mode=IN, jdbcType=INTEGER},
        #{totalAmount, mode=OUT, jdbcType=DECIMAL},
        #{orderCount, mode=OUT, jdbcType=INTEGER},
        #{errorCode, mode=OUT, jdbcType=VARCHAR}
    )}
</select>

Java 调用:

Java
Map<String, Object> params = new HashMap<>();
params.put("customerId", 1001);

session.selectOne("calcOrderTotal", params);

// 调用后从 Map 中获取 OUT 参数
BigDecimal totalAmount = (BigDecimal) params.get("totalAmount");
Integer orderCount = (Integer) params.get("orderCount");
String errorCode = (String) params.get("errorCode");

1.4 INOUT 参数(双向)

参数值传入后可能被存储过程修改,修改后的值写回原变量:

XML
<select id="paginateResults" statementType="CALLABLE" parameterType="map">
    {call paginate(
        #{pageSize, mode=IN, jdbcType=INTEGER},
        #{offset, mode=INOUT, jdbcType=INTEGER}
    )}
</select>
Java
Map<String, Object> params = new HashMap<>();
params.put("pageSize", 20);
params.put("offset", 0);  // 初始偏移量

session.selectOne("paginateResults", params);

// offset 已被存储过程更新为下一页起始值
Integer nextOffset = (Integer) params.get("offset");

二、resultMap 映射存储过程结果

2.1 存储过程返回结果集

当存储过程包含 SELECT 语句返回结果集时,使用 resultTyperesultMap 接收:

XML
<select id="getEmployeeList" statementType="CALLABLE" 
        resultMap="employeeResultMap">
    {call get_dept_employees(#{deptId, mode=IN, jdbcType=INTEGER})}
</select>

<resultMap id="employeeResultMap" type="Employee">
    <id property="id" column="emp_id"/>
    <result property="name" column="emp_name"/>
    <result property="salary" column="emp_salary"/>
    <result property="deptName" column="dept_name"/>
</resultMap>

2.2 同时返回结果集和 OUT 参数

存储过程可以既返回结果集又设置 OUT 参数,MyBatis 会同时处理两者:

XML
<select id="getPagedUsers" statementType="CALLABLE" 
        parameterType="map" resultMap="userResultMap">
    {call get_paged_users(
        #{pageNum, mode=IN, jdbcType=INTEGER},
        #{pageSize, mode=IN, jdbcType=INTEGER},
        #{totalCount, mode=OUT, jdbcType=INTEGER}
    )}
</select>
Java
Map<String, Object> params = new HashMap<>();
params.put("pageNum", 1);
params.put("pageSize", 10);

// 返回值是结果集列表,OUT 参数写入 params
List<User> users = session.selectList("getPagedUsers", params);
Integer totalCount = (Integer) params.get("totalCount");

2.3 多结果集处理

部分数据库支持存储过程返回多个结果集,使用 <resultMap> 嵌套映射:

XML
<select id="getOrderDetails" statementType="CALLABLE" 
        parameterType="map" resultMap="orderResultMap">
    {call get_order_with_items(
        #{orderId, mode=IN, jdbcType=INTEGER}
    )}
</select>

<resultMap id="orderResultMap" type="Order">
    <id property="id" column="order_id"/>
    <result property="orderDate" column="order_date"/>
    <collection property="items" ofType="OrderItem">
        <id property="id" column="item_id"/>
        <result property="productName" column="product_name"/>
        <result property="quantity" column="quantity"/>
    </collection>
</resultMap>

三、参数模式设置注意事项

3.1 必填属性检查清单

参数模式必填属性常见遗漏
INmode=IN(可选,默认即为 IN)
OUTmode=OUT + jdbcType忘记写 jdbcType 导致类型推断失败
INOUTmode=INOUT + jdbcType只写了 mode 未指定类型

3.2 jdbcType 的重要性

XML
<!-- 错误示例:缺少 jdbcType,当值为 null 时可能报错 -->
<select id="callProc" statementType="CALLABLE">
    {call my_proc(#{value, mode=OUT})}
</select>

<!-- 正确示例:显式指定 jdbcType -->
<select id="callProc" statementType="CALLABLE">
    {call my_proc(#{value, mode=OUT, jdbcType=VARCHAR})}
</select>

3.3 不同数据库的 OUT 参数差异

数据库OUT 参数语法注意事项
MySQLOUT param_name TYPE支持较好
Oracleparam_name OUT TYPE需注意 PL/SQL 块格式
PostgreSQLOUT param_name TYPE使用 CREATE FUNCTION 风格
SQL Server使用 OUTPUT 关键字需用 EXEC 调用

四、要点总结

要点说明
三种模式IN 单向传入、OUT 单向返回、INOUT 双向交互
OUT 参数容器推荐使用 Map 接收,调用后从中取值
resultMap 复用存储过程结果集的映射与普通查询完全一致
jdbcType 必填OUT 和 INOUT 参数必须指定,否则 NULL 值场景会报错
多结果集通过 collection 嵌套实现一对多映射

📝 发现内容有误?点击此处直接编辑

← 上一篇 游标结果处理
下一篇 → @One 与 @Many 关联
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库