{"record":{"id":"7ce128cf5a0ee6bd","repo":"mybatis/mybatis-3","slug":"cannot-construct-objects-with-collections-in-const","errorCode":null,"errorMessage":"Cannot construct objects with collections in constructors using multiple result sets yet!","messagePattern":"Cannot construct objects with collections in constructors using multiple result sets yet!","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java","lineNumber":1380,"sourceCode":"      metaObject.setValue(resultMapping.getProperty(), null);\n\n      // create new collection property\n      collectionProperty = instantiateCollectionPropertyIfAppropriate(resultMapping, metaObject);\n      final MetaObject targetMetaObject = configuration.newMetaObject(collectionProperty);\n\n      // create the pending objects\n      for (Object pendingCreation : pendingCreations) {\n        if (pendingCreation instanceof PendingConstructorCreation) {\n          final PendingConstructorCreation pendingConstructorCreation = (PendingConstructorCreation) pendingCreation;\n          targetMetaObject.add(pendingConstructorCreation.create(objectFactory));\n        }\n      }\n    }\n  }\n\n  private void verifyPendingCreationPreconditions(ResultMapping parentMapping) {\n    if (parentMapping != null) {\n      throw new ExecutorException(\n          \"Cannot construct objects with collections in constructors using multiple result sets yet!\");\n    }\n\n    if (!mappedStatement.isResultOrdered()) {\n      throw new ExecutorException(\"Cannot reliably construct result if we are not sure the results are ordered \"\n          + \"so that no new previous rows would occur, set resultOrdered on your mapped statement if you have verified this\");\n    }\n  }\n\n  private void createAndStorePendingCreation(ResultHandler<?> resultHandler, ResultSet resultSet,\n      DefaultResultContext<Object> resultContext, PendingConstructorCreation pendingCreation) throws SQLException {\n    final Object result = pendingCreation.create(objectFactory);\n    storeObject(resultHandler, resultContext, result, null, resultSet);\n    nestedResultObjects.clear();\n  }\n\n  //\n  // NESTED RESULT MAP (JOIN MAPPING)","sourceCodeStart":1362,"sourceCodeEnd":1398,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java#L1362-L1398","documentation":"MyBatis cannot build objects whose constructor takes a collection when the collection rows come from a separate result set (multi-result-set mapping, i.e. a ResultMapping with a foreign nested resultMap driven by another resultSet). This is a hard, documented engine limitation: pending constructor creations across multiple result sets are not implemented, so verifyPendingCreationPreconditions throws immediately when parentMapping != null.","triggerScenarios":"A statement returning multiple result sets (stored procedure or multi-select) where a resultMap maps one result set's rows into a constructor collection argument of an object built from another result set — the constructor mapping's parentMapping is non-null (rows arrive tagged with an outer parent mapping).","commonSituations":"Stored procedures returning master rows plus detail rows, wanting an immutable parent whose constructor accepts List<Child>; migrating setter-based collection mappings to constructor mappings while keeping the multi-resultSet design.","solutions":["Consolidate to a single result set with a JOIN and map the collection via nested resultMaps (not multiple resultSets).","Keep multiple result sets but map the collection into a setter/setter-based collection property instead of a constructor argument.","Materialize children in application code: fetch both result sets separately and construct the parent manually.","Track MyBatis releases — this limitation is long-standing; verify against the current version before designing around it."],"exampleFix":"// before (unsupported)\n<resultMap id=\"parentMap\" type=\"Parent\">\n  <constructor>\n    <arg property=\"children\" javaType=\"list\" resultMap=\"childMap\" resultSet=\"childrenRs\" column=\"id\"/>\n  </constructor>\n</resultMap>\n\n// after (supported): single joined result set, nested collection in constructor\n<resultMap id=\"parentMap\" type=\"Parent\">\n  <constructor>\n    <idArg column=\"id\" javaType=\"long\"/>\n    <arg property=\"children\" javaType=\"list\" resultMap=\"childMap\"/>\n  </constructor>\n</resultMap>","handlingStrategy":"validation","validationCode":"// reject the unsupported combination at startup instead of query time\nfor (MappedStatement ms : configuration.getMappedStatements()) {\n  if (ms instanceof MappedStatement real\n      && real.getResultMaps().stream().anyMatch(rm -> rm.getResultMappings().stream()\n          .anyMatch(rm2 -> rm2.getNestedResultMapId() != null && rm2.getResultSet() != null))) {\n    throw new IllegalStateException(ms.getId()\n        + \" combines multi-resultSet mappings with nested results;\"\n        + \" constructor collections across result sets are unsupported.\");\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not design stored procedures feeding constructor collection args from separate result sets — remap to a JOIN or setter collections.","Document the limitation in the project's data-access guidelines so schema/proc reviews catch it early."],"tags":["mybatis","multiple-resultsets","constructor-mapping","collections","unsupported"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}