mybatis-3: BaseBuilder#resolveTypeHandler does not account javaType for caching handlers

MyBatis version

3.4.2

Database vendor and version

Postgres 9.6

Steps to reproduce

I have result map with 2 Enums in it for handling in sumulationaly like that:

    <resultMap id="groupPlotFactMap" type="ru.rlh.egais.portal.api.dto.bo.PlotFact">
        <id column="pf_document_base_fkey" property="documentId"/>
        <id column="pf_unit" property="unit" typeHandler="EnumTypeHandler"/>
        <id column="pf_meta" property="meta" typeHandler="EnumTypeHandler"/>
    </resultMap>

And class:

public class PlotFact {
    private Unit unit;
    private FactMeta meta;
}

Expected result

Both fields mapped.

Actual result

Exception:

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'pf_meta' from result set.  Cause: java.lang.IllegalArgumentException: No enum constant ru.rlh.egais.portal.api.dto.enumeration.Unit.GROUP
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:77)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
    at com.sun.proxy.$Proxy1029.selectList(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230)
    at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:137)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:75)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
    at com.sun.proxy.$Proxy1115.search(Unknown Source)
    at ru.rlh.egais.portal.backend.service.PlotFactService.lambda$find$0(PlotFactService.java:82)
    at ru.rlh.egais.portal.backend.util.SearchUtils.makeSearch(SearchUtils.java:38)
   at ru.rlh.egais.portal.backend.service.PlotFactService.find(PlotFactService.java:81)

Indeed, database value GROUP belongs to secong enum ru.rlh.egais.portal.api.dto.enumeration.FactMeta instead of ru.rlh.egais.portal.api.dto.enumeration.Unit.

I start debugging and found what org.apache.ibatis.type.EnumTypeHandler instantiated once. And placed into registry by handler ignore handled target class. In source code even comment about that:

// javaType ignored for injected handlers see issue #746 for full detail TypeHandler<?> handler = typeHandlerRegistry.getMappingTypeHandler(typeHandlerType);

But issue https://github.com/mybatis/mybatis-3/issues/746 redirect to pull request https://github.com/mybatis/mybatis-3/pull/746 which seams irrelevant.

So could you please clarify why so?

If it desired I could try provide pull request for change caching.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Comments: 15 (7 by maintainers)

Commits related to this issue

Most upvoted comments

That error occurs when you specify typeHandler attribute when it is not necessary. Please try removing typeHandler attribute from <result /> as @kazuki43zoo suggested. If you use Map as resultType, you may need to add javaType="YourEnum" instead of typeHandler attribute.

I plan to overhaul type handler related code in future, but for now, this should be a reasonable workaround. If it does not work, please provide an executable example.

@emacarron @harawata

Is this a bug or not ?

Changes are follows:

  • 7ff1321d3b3a00c337db30d356feca05a5af3c2e (1st commit)
  • e92c2a2f1aacce52d7c1470b9aaa524dc8e9d1e7 (2nd commit)

When (as workaround) I create new noop handler just to be different in cached map:

public class FactMetaTypeHandler extends EnumTypeHandler<FactMeta> {
    public FactMetaTypeHandler(Class<FactMeta> type) {
        super(type);
    }
}

it works as expected.

@bokz53 ,

I plan to update type handler implementation in version 4 which will include java.lang.reflect.Type support, but there has been no progress as I am busy with my day job.

You didn’t post any code, so I am not sure if I understand your explanation correctly. I have seen some “generic type handler” ideas, but not all of them can be supported because of type erasure, I think.

You can try my work-in-progress branch and see if it resolves your own use case. The final implementation won’t be exactly the same, but the results should be close enough. https://github.com/harawata/mybatis-3/tree/type-based-handler-resolution And if it did not work as you expected, please create a (failing) test case or small demo project like these and share it on your repository.

Thanks a lot for the reply . I had a look for type-based-handler-resolution just now, and thought it can work in my situation. I will do a test in action to verify it at next few days, and report the result again.

@bokz53 ,

I plan to update type handler implementation in version 4 which will include java.lang.reflect.Type support, but there has been no progress as I am busy with my day job.

You didn’t post any code, so I am not sure if I understand your explanation correctly. I have seen some “generic type handler” ideas, but not all of them can be supported because of type erasure, I think.

You can try my work-in-progress branch and see if it resolves your own use case. The final implementation won’t be exactly the same, but the results should be close enough. https://github.com/harawata/mybatis-3/tree/type-based-handler-resolution And if it did not work as you expected, please create a (failing) test case or small demo project like these and share it on your repository.