Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TypeHandler lost information of actualTypeArguments when class is ParameterizedType #2187

Open
DavidTangWei opened this issue Feb 25, 2021 · 12 comments

Comments

@DavidTangWei
Copy link

DavidTangWei commented Feb 25, 2021

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
Copy link
Author

@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!

@harawata
Copy link
Member

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.

@wyl0706
Copy link

wyl0706 commented Sep 12, 2021

@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

@harawata
Copy link
Member

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

@half-dead
Copy link

@harawata any update on this issue?

@FlyInWind1
Copy link
Contributor

FlyInWind1 commented Nov 26, 2022

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

@FlyInWind1
Copy link
Contributor

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

@bunnyblueair
Copy link

any update on this issue?

@gr0l
Copy link

gr0l commented Oct 23, 2023

Any updates on this issue?

@la3rence
Copy link

Any update on this?

@Jasonyou-boy
Copy link

Is there any update?I had the same problem

@Vzhangs
Copy link

Vzhangs commented Jul 27, 2024

Any updates on this? I want to create a common List TypeHandler for a PostgreSQL composite type array column. But it might not be possible to implement it without getting the actualTypeArguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants