ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Mybatis 接收 Oracle 游标出参:TaoToken 统一 Key 下的可复制配置与验证

Mybatis 接收 Oracle 游标出参:TaoToken 统一 Key 下的可复制配置与验证 1. Mybatis 调用 Oracle 存储过程返回游标出参的完整链路与踩坑场景Mybatis 接收 Oracle 游标出参说白了就是让存储过程把sys_refcursor这种游标类型的结果集通过jdbcTypeCURSOR声明最终在 Java 侧拿到一个ListMap或List实体类。这件事在纯 JDBC 里写起来还算直观但一旦套上 Mybatis 的statementTypeCALLABLE参数模式、resultMap、jdbcType 三样东西必须同时对上错一个就是空集合或者直接抛异常。我见过最多的场景是这样的数据库里已经有一个现成的存储过程比如按身份证号查基本信息入参一个V_IDNO出参一个list1 OUT sys_refcursor。Java 侧想用 Mybatis 一把调完结果要么DATA取出来是null要么报ORA-01000游标超限要么resultMap没生效返回一堆HashMap里全是null值。这些问题的根子往往不在 SQL 本身而在参数声明和映射配置的细节上。这篇文章面向的是已经会写基础 Mybatis、但被 Oracle 游标出参卡住的同学。我会把存储过程、mapper XML、Java 调用三段代码完整贴出来再补上通过统一 Key 通道做接口鉴权和联调验证的部分让你一次跑通。核心检索词就三个Mybatis、Oracle 游标、出参映射。适合谁看适合正在做 Oracle 老系统对接、需要把存储过程结果集接进 Spring 项目的后端同学。先说清楚一个前提Oracle 的游标出参和 MySQL 那种直接SELECT返回结果集完全不是一回事。MySQL 里你写个CALL就能拿结果Oracle 必须显式声明OUT SYS_REFCURSOR而且 Mybatis 必须用resultMap而不是resultType来接。这个差异是后面所有配置的出发点。2. TaoToken 统一 Key 前置准备接口鉴权与联调通道在真正写 mapper 之前得先把调用通道准备好。因为存储过程联调往往不是本地直连数据库就完事很多团队会把数据库访问包一层 HTTP 接口或者用统一的模型/工具网关来做鉴权和转发。这里我用 TaoToken 的统一 Key 通道来演示它的作用是给接口调用提供一个统一的鉴权入口避免每个服务各写一套 Key 管理。TaoToken 的官网入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。注意 API 地址后面不加 UTM 参数直接用它做 Base URL 就行。你需要先去控制台创建一个 API Key控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite Key 管理页面在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 Key 之后联调阶段可以用模型对话页面先验证通道是否通地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果你后面要做长期的编码和 Agent 任务可以考虑 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite Claude Code 相关的接入说明在 https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 。这里要强调一点TaoToken 在这条链路里扮演的是统一鉴权和请求转发的角色不是数据库驱动也不是 Mybatis 的替代品。你的 mapper XML 和 Java 调用代码该怎么写还是怎么写TaoToken 负责的是当你的存储过程调用被包装成接口后接口层的 Key 校验和通道统一。所以前置准备的核心就是三件套Base URL、API Key、Model ID或接口标识。这三样在后面的配置片段里会具体出现。如果你用的是 Cline MCP 或者 Codex 这类工具来辅助联调配置里同样要写全这三件套。比如 Codex 的auth.json里需要填 Base URL 和 KeyCline 的 MCP 配置里需要指定接口地址和模型标识。这些配置的路径和字段名要和官方文档保持一致不能自己造。3. 可复制配置存储过程、mapper XML 与 Java 调用代码这一节是全文的核心直接给可复制的代码。先看 Oracle 存储过程假设表名是JBXX按IDNO查询CREATE OR REPLACE PROCEDURE A1( V_IDNO IN VARCHAR2, list1 OUT sys_refcursor ) AS BEGIN OPEN list1 FOR SELECT * FROM JBXX WHERE IDNO V_IDNO; END;存储过程本身很简单关键是出参list1的类型是sys_refcursor。接下来是 mapper XML这里有两个必须点statementTypeCALLABLE和jdbcTypeCURSOR配合resultMap。resultMap iddemo typejava.util.Map /resultMap select idgetjbxxMap statementTypeCALLABLE parameterTypejava.util.Map resultTypejava.util.List CALL A1( #{IDNO, modeIN, jdbcTypeVARCHAR}, #{DATA, modeOUT, jdbcTypeCURSOR, resultMapdemo} ) /select注意resultMapdemo是写在#{}里面的不是写在select标签上。这是最容易写错的地方。typejava.util.Map表示每行结果映射成 Map如果你想映射成实体类把 type 改成你的实体类全限定名并在 resultMap 里补上result column字段名 property属性名/。然后是 Java 调用代码public ListMapString, Object getjbxx(String IDNO) { MapString, Object map new HashMap(); map.put(IDNO, IDNO); map.put(DATA, OracleTypes.CURSOR); mapper.getjbxxMap(map); return (ListMapString, Object) map.get(DATA); }这里map.put(DATA, OracleTypes.CURSOR)是给 Mybatis 一个占位真正执行后结果会回填到map.get(DATA)。如果你用的是 MyBatis-Plus 或者 Spring 的Param注解方式参数名要和 XML 里的#{DATA}对上。如果你要把这个调用包装成 HTTP 接口并通过 TaoToken 统一 Key 通道鉴权可以在 Spring 的配置文件里加一段taotoken: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model-id: your-model-id对应的 JSON 配置片段比如给某些工具用{ baseUrl: https://taotoken.net/api, apiKey: sk-xxxxxxxx, modelId: your-model-id }这三件套 Base URL、Key、Model ID 在任何工具里出现时都要写全缺一个就连不通。4. 验证请求与成功结果一次跑通游标出参映射配置写完之后怎么确认真的跑通了我一般分三步验证。第一步先在数据库客户端里直接CALL A1(123456, :cursor)确认存储过程本身能返回数据。这一步排除 SQL 层面的问题。第二步写一个 JUnit 测试或者 main 方法直接调 mapper打印map.get(DATA)的 size 和第一条内容。Test public void testGetjbxx() { ListMapString, Object list service.getjbxx(123456); System.out.println(size list.size()); System.out.println(first list.get(0)); }成功的结果应该是控制台打印出size1或者更多first里能看到IDNO、NAME等字段的实际值。如果size0先别急着改代码去数据库确认这个IDNO是否真的有数据。如果first里全是null那就是 resultMap 的列名和属性名没对上或者type写成了 Map 但列名大小写不匹配。第三步通过 TaoToken 通道做接口层验证。用模型对话页面发一个请求确认 Key 有效、通道通畅。地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。如果接口层返回 200 且内容正常说明鉴权通道没问题剩下的就是业务逻辑。实测下来最容易出问题的是jdbcTypeCURSOR这个声明。有些 Oracle 驱动版本对CURSOR的大小写敏感必须全大写。另外OracleTypes.CURSOR的值是-10如果你手动写数字写错就废了。建议直接用OracleTypes.CURSOR常量。还有一个细节resultTypejava.util.List这个写法在部分 Mybatis 版本里会被忽略真正起作用的是resultMap。所以别纠结 resultType 写什么把 resultMap 配对就行。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth 对照联调过程中报错是常态这里列几个真实遇到的错误和排查方向。第一个401 Unauthorized。这个通常出现在接口层不是 Mybatis 层。原因一般是 TaoToken 的 API Key 没填、填错或者过期。排查方法去 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 重新生成一个 Key确认请求头里的 Authorization 字段格式正确。注意 Key 不要有多余空格。第二个local proxy failed。这个报错一般出现在你本地配了转发规则但目标地址不可达的时候。检查你的 Base URL 是不是写成了https://taotoken.net/api有没有多写斜杠或者少写。另外确认本地网络能正常访问这个地址不要配任何额外的转发层。第三个reading choices相关报错。这个通常出现在模型对话接口返回结构解析时说明返回的 JSON 里没有预期的choices字段。原因可能是 Model ID 填错了或者请求体格式不对。对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 检查请求参数。第四个OAuth相关报错。如果你用的是 Claude Code 接入方式可能会遇到 OAuth 校验失败。参考 https://taotoken.net/claudecode?utm_sourcetaotoken_aicg_blog_endutm_contentclaudecodeutm_campaignrewrite 里的配置说明确认认证方式选对了。有些场景用 API Key 就行不需要走 OAuth。除了这些接口层错误Mybatis 层还有两个高频问题。一个是ORA-01000: maximum open cursors exceeded说明游标没关闭检查你的 Java 代码里有没有正确消费map.get(DATA)以及连接池配置。另一个是Invalid column type说明jdbcType写错了游标出参必须是CURSOR。排查顺序建议先确认数据库存储过程能跑再确认 mapper 配置的 jdbcType 和 resultMap最后确认接口层 Key 和地址。一层一层来别跳。6. 语义一致收尾把游标出参接进你的实际项目到这里存储过程、mapper XML、Java 调用、统一 Key 通道验证这条链路就完整了。回到最开始的目标一次跑通游标出参映射。关键就三件事——statementTypeCALLABLE、jdbcTypeCURSOR、resultMap写在参数里。这三样配对剩下的就是数据本身的问题。如果你后面要把这套东西接进实际项目建议把 mapper 的调用封装成一个独立的 DAO 方法入参出参都走 Map这样存储过程改签名时改动最小。另外游标出参的结果集在 Java 侧拿到后记得做一次非空判断因为存储过程没OPEN成功时map.get(DATA)可能是null。接口鉴权这块TaoToken 的统一 Key 通道能帮你省掉每个服务单独管 Key 的麻烦。需要长期做编码和 Agent 任务的可以看看 Coding Plan入口在 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。接入文档和 API Keys 页面建议收藏联调时随时对照。
返回列表