Grégory Elhaimer
Grégory Elhaimer

Reputation: 2801

MyBatis - ResultMap according to javaType

Hello StackOverflowers,

There is something I don't get about MyBatis resultMap.

The model I'm working on is beeing updated. We decided to create a new graph of objects which reflects our future DB schema (the current one is awful).

To sum up our problem, here is a simple case: The current Object whith is related to table SITE is org.example.model.SiteModel. We created a new Object called org.example.entity.Site. (The package name is temporary).

The goal is now to use the existing SQL request developed thank to MyBatis and add a new ResultMap linked to the return type of our method.

Here is a an example:

/**
 * Get all site defined as template.
 */
@Select("SELECT * FROM SITE WHERE ISTEMPLATE = 'True'")
@ResultMap({"siteResMap" , "siteResultMap"})
@Options(statementType = StatementType.CALLABLE)
<T> List<T> findTemplates();

Then, in an XML configuration file, we defined the following mappings:

...
<resultMap id="siteResMap" type="org.example.entity.Site" />
<resultMap id="siteResultMap" type="org.example.model.SiteModel" />
...

And then we call the method from our DAO:

List<Site> site = siteDao.findTemplates();
List<SiteModel> siteMod = siteDao.findTemplates();

What we are expecting from this is a dynamic interpretation from MyBatis, taking the right ResultMap according to the computed return type.

But both list are shown as List<org.example.entity.Site> from debuger.

enter image description here

It makes me think that the first ResultMap is taken, ignoring the second one.

Am I missing something ? Is there a way to make MyBatis behave in such way ?

Regards

Upvotes: 3

Views: 1815

Answers (1)

Gr&#233;gory Elhaimer
Gr&#233;gory Elhaimer

Reputation: 2801

After a lot a research and code exploration, we found out that the String[] of ResultMap is not designed to link java return types to the resultMap.

This is function retrieving the resultmap (from org.apache.ibatis.executor.resultset.DefaultResultSetHandler)

public List<Object> handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity("handling results").object(mappedStatement.getId());

    final List<Object> multipleResults = new ArrayList<Object>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List<ResultMap> resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResulSets();
    if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) {
        ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
        if (parentMapping != null) {
          String nestedResultMapId = parentMapping.getNestedResultMapId();
          ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
          handleResultSet(rsw, resultMap, null, parentMapping);
    }
        rsw = getNextResultSet(stmt);
        cleanUpAfterHandlingResultSet();
        resultSetCount++;
      }
    }

    return collapseSingleResultList(multipleResults);
}

It explains why we always got a List of elements of type of the first resultMap.

We created a new Dao to map new object types.

Upvotes: 1

Related Questions