mybatis-3 icon indicating copy to clipboard operation
mybatis-3 copied to clipboard

TypeHandler lost information of actualTypeArguments when class is ParameterizedType

Open DavidTangWei opened this issue 4 years ago • 12 comments

MyBatis version

3.4.5

Database vendor and version

mysql 5.7+

Test case or example project

deserialize data in table test to POJO Test using mybatis mapper.xml.

create table test {
    `id` bigint pk,
    `names` json
}
//POJO Test    
class Test {
    private long id;
    public void setId(long id) {
        this.id = id;
    }
    private List<String> names;
    public void setNames(List<String> names) {
        this.names = names;
    }
}

// typehandler use jackson for deserialization 
// the clazz in constructor lost actualTypeArguments when real class is ParameterizedType
class JsonTypeHandler<T>(private var clazz: Class<T>) : BaseTypeHandler<T>() {
    
    protected val objectMapper = ObjectMapper()
   
    override fun setNonNullParameter(ps: PreparedStatement?, i: Int, parameter: T, jdbcType: JdbcType?) {
        ps?.setString(i, this.toJson(parameter))
    }

    private fun toJson(obj: T): String {
        try {
            return this.objectMapper.writeValueAsString(obj)
        } catch (e: Exception) {
            throw RuntimeException(e);
        }
    }
    <resultMap id="testMapper" type="Test">
        <result property="id" column="id" />
        <result property="names" column="names" 
                typeHandler="JsonTypeHandler"/>
    </resultMap>

After debug the source code of mybatis, the class in the constructor of TypeHandler is get from org.apache.ibatis.reflection.Reflector#setTypes. But when the type is ParameterizedType to be added, ignore the actualTypeArguments and only add rawType.

//org.apache.ibatis.reflection.Reflector
 private void addSetMethod(String name, Method method) {
   if (isValidPropertyName(name)) {
     setMethods.put(name, new MethodInvoker(method));
     Type[] paramTypes = TypeParameterResolver.resolveParamTypes(method, type);
     setTypes.put(name, typeToClass(paramTypes[0]));
   }
 }

 private Class<?> typeToClass(Type src) {
   Class<?> result = null;
   if (src instanceof Class) {
     result = (Class<?>) src;
   } else if (src instanceof ParameterizedType) {
     // ignore the `actualTypeArguments` and only add `rawType`.
     result = (Class<?>) ((ParameterizedType) src).getRawType();
   } 
   ...
   }
   return result;
 }

Expected result

TypeHandler need to get the real ParameterizedType. Otherwise, I need to write many useless code to create many class inherit TypeHandler to pass the ParameterizedType manual.

Actual result

TypeHandler lost information of actualTypeArguments when class is ParameterizedType

DavidTangWei avatar Feb 25 '21 03:02 DavidTangWei

@harawata hi. Why do TypeHandler ignore the actualTypeArguments when the type is ParameterizedType ? Do you have plan to give us another method to get the actualTypeArguments. I need your help! Please reply, thanks!

DavidTangWei avatar Mar 10 '21 15:03 DavidTangWei

Hello @DavidTangWei ,

It is a known limitation. I have been working on a patch, but it requires a lot of changes and I don't have much free time recently.

harawata avatar Mar 10 '21 16:03 harawata

@harawata I am experiencing the same problem, is there a plan to complete it? My problem link: https://stackoverflow.com/questions/69140073/how-to-use-generics-in-mybatis-jsontypehandler

wyl0706 avatar Sep 12 '21 14:09 wyl0706

@wyl0706 There will be a new comment when/if there is any news. :)

harawata avatar Sep 13 '21 18:09 harawata

@harawata any update on this issue?

half-dead avatar Sep 29 '22 07:09 half-dead

I am trying to work on this https://github.com/FlyInWind1/mybatis-3

FlyInWind1 avatar Nov 26 '22 07:11 FlyInWind1

I have impl ListTypeHandler. I pass ResolvedType (wrap jackson JavaType) to TypeHandler, instead of Class. link https://github.com/FlyInWind1/mybatis-3 And this is my mybatis-plus https://github.com/FlyInWind1/mybatis-plus

FlyInWind1 avatar Dec 07 '22 16:12 FlyInWind1

any update on this issue?

bunnyblueair avatar Mar 23 '23 23:03 bunnyblueair

Any updates on this issue?

gr0l avatar Oct 23 '23 12:10 gr0l