存储过程调用
预计阅读时间: 约 6 分钟
在 MyBatis 中调用数据库存储过程是处理复杂业务逻辑的重要手段。存储过程将一组 SQL 语句预编译并存储在数据库端,通过 CALL 语句即可触发执行,既能减少网络往返,又能利用数据库的执行计划缓存提升性能。
一、CALL 语句基础
1.1 基本语法
MyBatis 通过 statementType="CALLABLE" 声明来调用存储过程,XML 映射文件中使用 {call procedure_name(...)} 格式:
XML
<select id="callProcedure" statementType="CALLABLE">
{call get_user_stats(#{userId, mode=IN})}
</select>
1.2 statementType 说明
| statementType | 说明 | 适用场景 |
|---|---|---|
STATEMENT | 直接使用 Statement 执行 | 简单静态 SQL |
PREPARED | 使用 PreparedStatement(默认) | 参数化查询 |
CALLABLE | 使用 CallableStatement | 存储过程调用 |
要点: 只有 statementType="CALLABLE" 才能正确解析存储过程的参数模式(IN/OUT/INOUT)。
二、CallableStatement 配置
2.1 参数模式设置
存储过程参数需要通过 mode 属性显式声明方向:
XML
<select id="callProc" statementType="CALLABLE">
{call calculate_salary(
#{deptId, mode=IN, jdbcType=INTEGER},
#{totalSalary, mode=OUT, jdbcType=DECIMAL}
)}
</select>
2.2 常用属性对照
| 属性 | 必填 | 说明 |
|---|---|---|
mode | 是 | IN、OUT 或 INOUT,定义参数方向 |
jdbcType | 推荐 | 指定 JDBC 类型,避免类型推断错误 |
javaType | 否 | Java 类型,用于复杂类型映射 |
typeHandler | 否 | 自定义类型处理器 |
三、基本参数传递
3.1 纯输入参数调用
XML
<!-- 仅传入参数,存储过程内部处理逻辑 -->
<select id="refreshCache" statementType="CALLABLE">
{call refresh_user_cache(#{userId, mode=IN, jdbcType=VARCHAR})}
</select>
对应 Java 调用:
Java
public void refreshCache(String userId) {
session.selectOne("refreshCache", Map.of("userId", userId));
}
3.2 输入 + 输出参数
XML
<select id="getDepartmentStats" statementType="CALLABLE" parameterType="map">
{call get_dept_stats(
#{deptId, mode=IN, jdbcType=INTEGER},
#{empCount, mode=OUT, jdbcType=INTEGER},
#{avgSalary, mode=OUT, jdbcType=DECIMAL}
)}
</select>
Java 调用时传入 Map 接收输出参数:
Java
Map<String, Object> params = new HashMap<>();
params.put("deptId", 10);
session.selectOne("getDepartmentStats", params);
Integer empCount = (Integer) params.get("empCount");
BigDecimal avgSalary = (BigDecimal) params.get("avgSalary");
3.3 使用 @Select 注解调用
Java
@Select("{call get_user_by_id(#{userId, mode=IN, jdbcType=INTEGER})}")
@Options(statementType = org.apache.ibatis.mapping.StatementType.CALLABLE)
User getUserById(@Param("userId") Integer userId);
四、要点总结
| 要点 | 说明 |
|---|---|
statementType="CALLABLE" | 调用存储过程必须声明,否则参数模式无法解析 |
显式声明 mode | OUT 和 INOUT 参数必须指定 mode=OUT 或 mode=INOUT |
指定 jdbcType | 避免数据库驱动类型推断失败,特别是 NULL 值场景 |
| 输出参数用 Map | 多 OUT 参数推荐使用 Map 传递,调用后从 Map 取值 |
| 返回值处理 | 若存储过程返回结果集,使用 <select> + resultType 接收 |
存储过程调用是 MyBatis 高级查询的基础,掌握参数传递方式后,可以进一步学习输入输出参数的精细配置和游标结果处理。
📝 发现内容有误?点击此处直接编辑