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
- Decide the relationship cardinality: keep @One for a single referenced object or @Many for a collection, and delete the other sub-annotation entirely.
- If both a single object and a collection are genuinely needed, model them as two separate @Result properties each with its own sub-annotation.
- 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
- Model to-one and to-many relations as separate properties from the start.
- When changing @One to @Many, delete the unused sub-annotation.
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
- Should be specified either value() or name() attribute in th
- Cannot use both value() and name() attribute in the @CacheNa
- Detected conflicting annotations '%s' and '%s' on '%s'.
- Could not find a statement annotation that correspond a curr
- %s already contains value for %s
AI-assisted analysis of baomidou/mybatis-plus@bf67d90747 (2026-08-14).
Data as JSON: /api/errors/4d57aa7e5403e9d0.
Report an issue: GitHub.