在用 MyBatis 调用 Oracle 存储过程时,遇到返回空数据的情况。排查了半天。。。
报错
[debug,137] - ==> Preparing: {call some_procedure( ?, ?, ?, ?, ?, ?, ? )}
[debug,137] - ==> Parameters: 2(String), 1(String), 2026-07-21 21:29:53(String), 2026-07-22 21:29:53(String), A(String), B(String)
ERROR [internalAfterStatementExecute,518] - slow sql 5089 millis. {call some_procedure(
?,
?,
?,
?,
?,
?,
?
)} ["2","1","2026-07-21 21:29:53","2026-07-22 21:29:53","A","B"]
[debug,49] - Closing non transactional SqlSession
返回空。但是在 SQL developer 中调用,返回正常,有返回数据。
而且 MyBatis 开启了 Trace 日志级别,也看不到任何返回信息。
Oracle SQL developer 中调用
var cur refcursor;
begin
some_procedure('2','1','2026-07-21 21:29:53','2026-07-22 21:29:53','A','B',:cur);
end;
/
print :cur;
显示
121 rows selected.
解决方案
出现这个问题的原因是:对于 Oracle 中返回游标(CURSOR)作为 OUT 参数的存储过程,MyBatis 不会直接将结果集作为 Mapper 方法的返回值返回,而是将结果集封装到一个 List 中并放入你传入的 Map 参数对象里(key 为你在 XML 中配置的 result)。
之前代码尝试直接通过 someMapper.list(params) 接收返回值,因此返回了空。
不再直接 return someMapper.list(params);,而是改为从传入的 params 这个 Map 中提取 result 键对应的值,即转换为 List
git diff
mapper 文件:
- public List<SomeVO> list(Map<String, Object> params);
+ public void list(Map<String, Object> params);
impl 文件:
- return someMapper.list(params);
+ someMapper.list(params);
+ List<SomeVO> result = (List<SomeVO>) params.get("result");
+ return result != null ? result : new java.util.ArrayList<>();
警告信息
// List<SomeVO> result = (List<SomeVO>) params.get("result");
Type safety: Unchecked cast from Object to List<SomeVO>
params.get(“result”) 是从 MyBatis CALLABLE 存储过程 OUT 游标参数取出的 Object,类型只能在运行时确定,因此无法做真正的编译期类型检查。
最规范的修复是在执行该强制转换的方法上添加 @SuppressWarnings(“unchecked”) 注解
关于作者 🌱
我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式