question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

TypeHandler lost information of actualTypeArguments when class is ParameterizedType

See original GitHub issue

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

Issue Analytics

  • State:open
  • Created 3 years ago
  • Reactions:2
  • Comments:7 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
harawatacommented, Mar 10, 2021

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.

1reaction
half-deadcommented, Sep 29, 2022

@harawata any update on this issue?

Read more comments on GitHub >

github_iconTop Results From Across the Web

ParameterizedType (Java Platform SE 8 ) - Oracle Help Center
Method Detail. getActualTypeArguments. Type[] getActualTypeArguments(). Returns an array of Type objects representing the actual type arguments to this type.
Read more >
java - How to get the actual type arguments to an indirectly ...
or Base<E> will be made, that type information will be lost due to ... This class will have its type parameters available for...
Read more >
MapperAnnotationBuilder.java example - Javatips.net
This class describes the usage of MapperAnnotationBuilder.java. ... Maps if there is not MapKey annotation Type[] actualTypeArguments = parameterizedType.
Read more >
Register Generic Classes using Generic Type Handler
Write the code for all the required combinations for all data types that can be used in your application. Important. For Java, before...
Read more >
R8 FullMode in AGP 7.0.0-beta01 transforming ... - Issue Tracker
ParameterizedType ?: throw RuntimeException("Invalid TypeToken; must specify type parameters")).actualTypeArguments[0] } private abstract class ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found