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
- TypeHandlerRegistry#getMappingTypeHandler will check whether the TypeHandler need a Class for construct. #995 — committed to FlyInWind1/mybatis-3 by FlyInWind1 2 years ago
That error occurs when you specify
typeHandlerattribute when it is not necessary. Please try removingtypeHandlerattribute from<result />as @kazuki43zoo suggested. If you use Map asresultType, you may need to addjavaType="YourEnum"instead oftypeHandlerattribute.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:
When (as workaround) I create new noop handler just to be different in cached map:
it works as expected.
Thanks a lot for the reply . I had a look for
type-based-handler-resolutionjust 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.Typesupport, 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.