-
Notifications
You must be signed in to change notification settings - Fork 13k
Closed
Description
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
AndLvovSky, FlyInWind1, CLD1994, la3rence, nahoj and 1 more