mybatis/mybatis-3 · error · IllegalStateException

Mapping is missing column attribute for property {}

Error message

Mapping is missing column attribute for property {}

What it means

Thrown by ResultMapping.Builder.validate() when a result mapping has no column, no composite columns, and is not backed by a nested resultMap. MyBatis requires a column for every plain mapping because it is the only way to know which JDBC column feeds the property. Only mappings that select into a nested resultMap (nestedResultMapId set) or use composite columns are exempt.

Source

Thrown at src/main/java/org/apache/ibatis/mapping/ResultMapping.java:169

    public ResultMapping build() {
      // lock down collections
      resultMapping.flags = List.copyOf(resultMapping.flags);
      resultMapping.composites = List.copyOf(resultMapping.composites);
      validate();
      return resultMapping;
    }

    private void validate() {
      // Issue #697: cannot define both nestedQueryId and nestedResultMapId
      if (resultMapping.nestedQueryId != null && resultMapping.nestedResultMapId != null) {
        throw new IllegalStateException(
            "Cannot define both nestedQueryId and nestedResultMapId in property " + resultMapping.property);
      }
      // Issue #4 and GH #39: column is optional only in nested resultMaps but not in the rest
      if (resultMapping.nestedResultMapId == null && resultMapping.column == null
          && resultMapping.composites.isEmpty()) {
        throw new IllegalStateException("Mapping is missing column attribute for property " + resultMapping.property);
      }
      if (resultMapping.getResultSet() != null) {
        int numColumns = 0;
        if (resultMapping.column != null) {
          numColumns = resultMapping.column.split(",").length;
        }
        int numForeignColumns = 0;
        if (resultMapping.foreignColumn != null) {
          numForeignColumns = resultMapping.foreignColumn.split(",").length;
        }
        if (numColumns != numForeignColumns) {
          throw new IllegalStateException(
              "There should be the same number of columns and foreignColumns in property " + resultMapping.property);
        }
      }
    }

    public Builder column(String column) {

View on GitHub (pinned to 008069adb1)

Solutions

  1. Add the column attribute: <result property="prop" column="col_name"/>.
  2. If the value comes from another statement's result map, point at a nested resultMap via resultMap="..." so nestedResultMapId is set.
  3. For multi-column mappings (e.g. composite keys), supply <constructor>/<id> composites or columnPrefix so composites is non-empty.
  4. If building programmatically, call builder.column("col_name") before build().

Example fix

<!-- before -->
<result property="userName" javaType="string"/>
<!-- after -->
<result property="userName" column="user_name" javaType="string"/>
Defensive patterns

Strategy: validation

Validate before calling

// before build(): a plain mapping needs a column, composites, or a nested resultMap
boolean ok = rm.nestedResultMapId != null || rm.column != null || !rm.composites.isEmpty();
// with the Builder: always call .column(...) for non-nested mappings

Prevention

When it happens

Trigger: Building a ResultMapping via new ResultMapping.Builder(configuration, "prop", null, javaType).build(), or an XML resultMap entry like <result property="prop" javaType="..."/> with no column attribute and no nested resultMap select.

Common situations: Hand-writing a resultMap and forgetting the column attribute; using <id>/<result> elements that only carry javaType; programmatically constructing ResultMapping without calling builder.column(...).

Related errors


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/ffdca0dae5267622. Report an issue: GitHub.