Skip to content

When using @ConstructorArgs, shouldn't implicit type resolution be run against the constructor arguments? #2787

Closed
@sp00m

Description

@sp00m

MyBatis version

3.5.11

Steps to reproduce

class MyType {
    final String computed;
    public MyType(Integer i) {
        this.computed = i + "";
    }
}
@Select("...")
@ConstructorArgs({ @Arg(column = "...", name = "i") })
List<MyType> select();

Expected result

MyBatis should understand that i is expected to be of type Integer given it's the type of the matching argument in the constructor.

Actual result

I get in the logs:

Found a constructor with arg names [i], but the type of 'i' did not match. Specified: [java.lang.Object] Declared: [java.lang.Integer]

I believe this is due to the fact that MapperAnnotationBuilder#applyConstructorArgs calls MapperBuilderAssistant#buildResultMapping, which tries to resolve the Java type by looking at the class' fields, instead of by looking at the constructor args as one could think given @ConstructorArgs is used.

In my example, because MyType doesn't have a field named i, only a constructor arg, then it doesn't successfully resolve the type of i and defaults to Object (see MapperBuilderAssistant#resolveResultJavaType).

I believe when @ConstructorArgs is used, then implicit type resolution should be run against the constructor arguments.

Workaround

Explicitly specify the Java type to use:

@Arg(column = "i", name = "i", javaType = Integer.class)

Side notes

Relates to #2207, although not exactly the same case I believe.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions