mybatis调用存储过程需设statementtype="callable",用#{}绑定mode=in/out参数并显式指定jdbctype;输出值通过map或对象返回,mysql需驱动8.0+支持。

MyBatis 执行存储过程并获取输出参数,核心在于正确配置 <select></select> 或 <update></update> 标签的 statementType="CALLABLE",并使用 #{} 绑定带方向(mode)的参数。
1. 存储过程定义示例(以 MySQL 为例)
先确保数据库中存在带输入、输出参数的存储过程:
DELIMITER $$
CREATE PROCEDURE GetUserById(
IN p_user_id INT,
OUT p_user_name VARCHAR(50),
OUT p_user_age INT
)
BEGIN
SELECT name, age INTO p_user_name, p_user_age
FROM users WHERE id = p_user_id;
END$$
DELIMITER ;
2. Mapper 接口定义
接口方法参数建议用 Map 或自定义对象封装输入/输出参数(推荐 Map,更直观):
public interface UserMapper {
void getUserById(Map<string object> params);
}</string>
注意:方法返回类型为 void,因为输出参数通过传入的 Map 返回。
3. XML Mapper 配置(关键!)
必须设置 statementType="CALLABLE",且每个参数需明确 mode(IN、OUT 或 INOUT),Java 类型(javaType)和 JDBC 类型(jdbcType)建议显式指定:
<select id="getUserById" statementtype="CALLABLE" parametertype="map">
{ CALL GetUserById(
#{userId, mode=IN, jdbcType=INTEGER},
#{userName, mode=OUT, javaType=string, jdbcType=VARCHAR},
#{userAge, mode=OUT, javaType=int, jdbcType=INTEGER}
) }
</select>
-
花括号
{}是必需语法,表示 CallableStatement 调用 -
mode=IN对应输入参数;mode=OUT表示该参数由数据库写回,调用后可从 Map 中取值 -
jdbcType建议不省略,尤其对 NULL 值或特殊类型(如 DATE、CLOB)更健壮 - MySQL 默认不支持
OUT参数在预编译语句中直接映射,需确认驱动版本(推荐 MySQL Connector/J 8.0+)并开启allowMultiQueries=true(非必需,但部分旧版环境可能需要)
4. Java 调用示例
传入 Map 封装输入值,调用后从同一 Map 获取输出参数:
Map<string object> params = new HashMap();
params.put("userId", 123);
userMapper.getUserById(params); // 执行存储过程
String name = (String) params.get("userName");
Integer age = (Integer) params.get("userAge");
System.out.println("Name: " + name + ", Age: " + age);</string>
如果使用自定义对象(如 UserProcParam),需确保有对应 getter/setter,并在 XML 中用 #{userName} 直接引用属性名,MyBatis 会自动映射。
5. 注意事项
- Oracle / SQL Server 等数据库语法略有差异(如 Oracle 使用
:=赋值,SQL Server 支持EXEC),但 MyBatis 的CALLABLE方式通用,只需调整 SQL 字符串内容 - 若存储过程返回结果集(
SELECT),可用<resultmap></resultmap>映射,同时保留mode=OUT参数 - 事务控制需由外部 Service 方法统一管理,MyBatis 本身不干预存储过程内部事务
- 调试时可在日志中开启
org.apache.ibatis的 DEBUG 日志,查看实际执行的 CallableStatement 和参数绑定情况
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











