baomidou/mybatis-plus · error · BuilderException

Cannot use both @One and @Many annotations in the same @Resu

Error message

Cannot use both @One and @Many annotations in the same @Result

What it means

Thrown by MybatisMapperAnnotationBuilder.hasNestedResultMap when a single @Result in a @Results mapping declares resultMap ids in both its @One and @Many sub-annotations. A result property can be either a single referenced object (@One) or a collection (@Many), never both, so the builder fails fast during mapper annotation parsing.

Source

Thrown at mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/MybatisMapperAnnotationBuilder.java:481

            columnPrefix = result.many().columnPrefix();
        }
        return columnPrefix;
    }

    private String nestedResultMapId(Result result) {
        String resultMapId = result.one().resultMap();
        if (resultMapId.length() < 1) {
            resultMapId = result.many().resultMap();
        }
        if (!resultMapId.contains(StringPool.DOT)) {
            resultMapId = type.getName() + StringPool.DOT + resultMapId;
        }
        return resultMapId;
    }

    private boolean hasNestedResultMap(Result result) {
        if (result.one().resultMap().length() > 0 && result.many().resultMap().length() > 0) {
            throw new BuilderException("Cannot use both @One and @Many annotations in the same @Result");
        }
        return result.one().resultMap().length() > 0 || result.many().resultMap().length() > 0;
    }

    private String nestedSelectId(Result result) {
        String nestedSelect = result.one().select();
        if (nestedSelect.length() < 1) {
            nestedSelect = result.many().select();
        }
        if (!nestedSelect.contains(StringPool.DOT)) {
            nestedSelect = type.getName() + StringPool.DOT + nestedSelect;
        }
        return nestedSelect;
    }

    private boolean isLazy(Result result) {
        boolean isLazy = configuration.isLazyLoadingEnabled();
        if (result.one().select().length() > 0 && FetchType.DEFAULT != result.one().fetchType()) {

View on GitHub (pinned to bf67d90747)

Solutions

  1. Decide the relationship cardinality: keep @One for a single referenced object or @Many for a collection, and delete the other sub-annotation entirely.
  2. If both a single object and a collection are genuinely needed, model them as two separate @Result properties each with its own sub-annotation.
  3. Rebuild and re-run so mapper parsing validates the corrected annotation.

Example fix

// before
@Results(id = "orderRM", value = {
  @Result(column = "user_id", property = "user",
          one = @One(resultMap = "userRM"),
          many = @Many(resultMap = "itemRM"))
})

// after
@Results(id = "orderRM", value = {
  @Result(column = "user_id", property = "user", one = @One(resultMap = "userRM")),
  @Result(column = "order_id", property = "items", many = @Many(resultMap = "itemRM"))
})
Defensive patterns

Strategy: validation

Validate before calling

// static check over @Results of every mapper method
for (java.lang.reflect.Method m : mapper.getMethods()) {
    org.apache.ibatis.annotations.Results rs = m.getAnnotation(org.apache.ibatis.annotations.Results.class);
    if (rs == null) continue;
    for (org.apache.ibatis.annotations.Result r : rs.value()) {
        if (r.one().resultMap().length() > 0 && r.many().resultMap().length() > 0) {
            throw new IllegalStateException(m + " uses both @One and @Many resultMaps");
        }
    }
}

Try / catch

Catch BuilderException during mapper parsing; locate the @Result named by the stack trace's mapper method and split into two properties.

Prevention

When it happens

Trigger: Annotating one @Result(column = "x", one = @One(resultMap = "userRM"), many = @Many(resultMap = "orderRM")) — both resultMap strings non-empty triggers the check.

Common situations: Copy-pasting a @Result and switching @One to @Many without clearing the old attribute; evolving a to-one relation into a to-many relation and forgetting to delete the @One part.

Related errors


AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14). Data as JSON: /api/errors/4d57aa7e5403e9d0. Report an issue: GitHub.