{"record":{"id":"3e5175d0739e211a","repo":"mybatis/mybatis-3","slug":"cursor-results-cannot-be-mapped-to-multiple-result","errorCode":null,"errorMessage":"Cursor results cannot be mapped to multiple resultMaps","messagePattern":"Cursor results cannot be mapped to multiple resultMaps","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java","lineNumber":259,"sourceCode":"        resultSetCount++;\n      }\n    }\n\n    return collapseSingleResultList(multipleResults);\n  }\n\n  @Override\n  public <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException {\n    ErrorContext.instance().activity(\"handling cursor results\").object(mappedStatement.getId());\n\n    ResultSetWrapper rsw = getFirstResultSet(stmt);\n\n    List<ResultMap> resultMaps = mappedStatement.getResultMaps();\n\n    int resultMapCount = resultMaps.size();\n    validateResultMapsCount(rsw, resultMapCount);\n    if (resultMapCount != 1) {\n      throw new ExecutorException(\"Cursor results cannot be mapped to multiple resultMaps\");\n    }\n\n    ResultMap resultMap = resultMaps.get(0);\n    return new DefaultCursor<>(this, resultMap, rsw, rowBounds);\n  }\n\n  private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {\n    ResultSet rs = null;\n    SQLException e1 = null;\n\n    try {\n      rs = stmt.getResultSet();\n    } catch (SQLException e) {\n      // Oracle throws ORA-17283 for implicit cursor\n      e1 = e;\n    }\n\n    try {","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java#L241-L277","documentation":"DefaultResultSetHandler.handleCursorResultSets only supports a single ResultSet mapping: when a statement run through selectCursor()/Cursor return has more than one resultMap declared (multiple result sets), it throws this ExecutorException because a Cursor is a streaming single-result API.","triggerScenarios":"sqlSession.selectCursor(...) (or a mapper method returning Cursor<T>) on a mapped statement whose resultMaps list size != 1 — e.g. two <resultSet> mappings in a stored-procedure mapper, or resultType plus an extra resultMap after refactoring.","commonSituations":"Converting a selectList call backed by a multi-resultset stored procedure to selectCursor for streaming; annotating a mapper method with @ResultMap lists yielding multiple maps; copy-pasting a multi-resultset statement and switching its consumer to Cursor.","solutions":["Use selectList/List-returning mapper methods for statements that return multiple result maps","Split the stored procedure or statement so each Cursor maps exactly one result set","If you only need the first result set, define a dedicated statement with a single resultMap for it"],"exampleFix":"// before: statement maps 2 resultSets\nCursor<Order> c = session.selectCursor(\"sel.ordersWithItems\"); // throws\n// after: dedicated single-resultMap statement\nCursor<Order> c = session.selectCursor(\"sel.ordersOnly\");\nList<Item> items = session.selectList(\"sel.itemsOnly\");","handlingStrategy":"validation","validationCode":"// Only use Cursor when the statement maps exactly one result set\nMappedStatement ms = session.getConfiguration().getMappedStatement(\"sel.ordersWithItems\");\nif (ms.getResultMaps().size() != 1) { throw new UnsupportedOperationException(\"Use selectList for multi-resultMap statements\"); }\ntry (Cursor<Order> c = session.selectCursor(\"sel.ordersWithItems\")) { ... }","typeGuard":null,"tryCatchPattern":"try (Cursor<Order> c = session.selectCursor(stmt)) { ... } catch (ExecutorException e) { if (e.getMessage().contains(\"multiple resultMaps\")) { fallback to session.selectList(stmt); } else throw e; }","preventionTips":["Reserve Cursor APIs for single-result-set statements","Keep a project convention: streaming consumers get dedicated single-resultMap statements","Review multi-resultset stored procs before switching consumers to Cursor"],"tags":["mybatis","cursor","resultmap","streaming"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}