Skip to content

Lookup constructor argument types based on index when arg name not provided #2618

Open
@uklance

Description

@uklance

Mybatis currently has the ability to match constructor args declared in mapper xml to constructors in bean classes using the parameter name. This mapping allows mybatis to:

  • Determine which TypeHandler to use to get each column from the ResultSet [see DefaultResultSetHandler]
  • Determine which Constructor to invoke with the List of values [see DefaultObjectFactory]

    Eg:

    <resultMap id="account" type="com.company.Account">
       <constructor>
          <arg name="accountId" column="ACCOUNT_ID" />
          <arg name="accountName" column="ACCOUNT_NAME" />
          <arg name="accountType" column="ACCOUNT_TYPE" />
       </constructor>
    </resultMap>

    My model classes do not contain the parameter name information (see ParamNameUtil.getParamNames(Constructor)) and I do not have control over these (so can't add annotations etc).

    I'd like a change in mybatis to support the same behavior but with the following xml

    <resultMap id="account" type="com.company.Account">
       <constructor>
          <arg column="ACCOUNT_ID" />
          <arg column="ACCOUNT_NAME" />
          <arg column="ACCOUNT_TYPE" />
       </constructor>
    </resultMap>

    Unfortunately when I try this mybatis:

    • defaults the javaType for each argument to java.lang.Object
    • uses the UnknownTypeHandler to read values from the ResultSet
    • tries to invoke the constructor com.company.Account(Object, Object, Object) and fails with NoSuchMethodException

    It would be great if mybatis could look for a single constructor with 3 arguments and determine the types from that. If there were more than one constructor with 3 arguments I think it would be fair for mybatis to throw an exception.

    As a workaround I have to specifically tell mybatis the types but I feel this is repeating myself, and that mybatis should be able to use reflection to get the javaTypes

    <resultMap id="account" type="com.company.Account">
       <constructor>
          <arg column="ACCOUNT_ID" javaType="java.lang.Long" />
          <arg column="ACCOUNT_NAME" javaType="java.lang.String" />
          <arg column="ACCOUNT_TYPE" javaType="java.lang.String" />
       </constructor>
    </resultMap>

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions