必须设置statementtype="callable"且out参数显式声明mode=out和jdbctype,否则mybatis无法回写结果;游标需配专用resultmap,参数容器须为可修改map或含setter的实体类。

必须用 statementType="CALLABLE",且所有 OUT 参数的 mode 要显式设为 OUT,否则 MyBatis 不会把结果回写到参数容器里。
MyBatis XML 中必须声明 statementType="CALLABLE"
这是最关键的开关。默认 statementType="PREPARED",MyBatis 会把它当普通 SQL 解析,根本不会触发存储过程调用协议。哪怕你写了 {call ...} 语法,没这个属性照样报错或静默失败。
-
statementType必须写在<select></select>、<update></update>或<insert></insert>标签上,不能只靠 SQL 字符串识别 - Oracle 存储过程返回游标(
sys_refcursor)时,也必须加这个属性,否则jdbcType="CURSOR"会被忽略 - 别依赖“不写就默认”,MyBatis 不会自动推断存储过程意图
OUT 参数必须用 mode=OUT + 显式 jdbcType
Oracle 对数据类型敏感,MyBatis 需要提前知道 JDBC 如何绑定和读取 OUT 参数。漏掉 mode 或 jdbcType,轻则值为 null,重则抛 SQLException: Invalid column type。
-
#{paramName, mode=OUT, jdbcType=VARCHAR}——jdbcType必须匹配 Oracle 实际定义的类型,比如VARCHAR2对应VARCHAR,NUMBER对应NUMERIC或INTEGER - 如果 OUT 是游标,
jdbcType固定写CURSOR,且必须配resultMap和javaType=java.sql.ResultSet - 别用
parameterMap(已废弃),全用parameterType+ 内联#{...}方式更可控
参数容器必须是可修改的 Map 或实体类
MyBatis 把 OUT 参数的值直接 set 进你传入的对象字段或 Map 的 key。如果传的是不可变对象(如 String)、原始类型(int)、或 final 字段,值永远拿不到。
- 推荐用
HashMap<string object></string>:入参 put 进去,出参自动塞进同名 key,调用后直接 get - 也可用自定义实体类,但字段必须有 public setter,且命名与 XML 中
#{xxx}的 key 一致 - 不要传
Integer、String等包装类/不可变类型作 OUT 参数载体——它们无法被 MyBatis 修改内部值 - 测试时打印整个 Map 或实体对象,确认 OUT 键是否已存在且非
null
Oracle 游标必须配独立 resultMap,不能复用已有映射
MyBatis 对游标结果集的解析完全依赖 resultMap 定义。如果误用主表的 BaseResultMap,会报 Invalid column index 或字段映射全为空。
- 游标专用的
resultMap必须明确指定每个列的column和property,大小写需与 Oracle 查询结果一致(通常大写) -
resultMap的type可以是 POJO 类,也可以是java.util.HashMap,但后者要注意 key 全是大写字符串 - XML 中引用时,大小写敏感:
resultMap="ProcedureInfoMap"必须和<resultmap id="ProcedureInfoMap"></resultmap>完全一致
最常被忽略的一点:Oracle 存储过程中对 sys_refcursor 的 OPEN ... FOR 语句,其 SELECT 字段顺序和别名,必须和 MyBatis 的 resultMap 列定义严格对应——差一个位置,整行数据就错位了。











