mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 01:28:24 +08:00
feat: add typeHandler support generic type
This commit is contained in:
parent
6c0927ffff
commit
26dc943344
@ -17,19 +17,39 @@ package com.mybatisflex.core.handler;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONWriter;
|
||||
import com.alibaba.fastjson2.TypeReference;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
*/
|
||||
public class Fastjson2TypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
|
||||
private final Class<?> propertyType;
|
||||
private Class<?> genericType;
|
||||
private Type type;
|
||||
|
||||
public Fastjson2TypeHandler(Class<?> type) {
|
||||
this.propertyType = type;
|
||||
public Fastjson2TypeHandler(Class<?> propertyType) {
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
|
||||
public Fastjson2TypeHandler(Class<?> propertyType, Class<?> genericType) {
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = genericType;
|
||||
this.type = TypeReference.collectionType((Class<? extends Collection>) propertyType, genericType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseJson(String json) {
|
||||
if (genericType != null && Collection.class.isAssignableFrom(propertyType)) {
|
||||
return JSON.parseObject(json, type);
|
||||
} else {
|
||||
return JSON.parseObject(json, propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(Object object) {
|
||||
|
||||
@ -18,18 +18,38 @@ package com.mybatisflex.core.handler;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
*/
|
||||
public class FastjsonTypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
|
||||
private final Class<?> propertyType;
|
||||
private Class<?> genericType;
|
||||
private Type type;
|
||||
|
||||
public FastjsonTypeHandler(Class<?> type) {
|
||||
this.propertyType = type;
|
||||
public FastjsonTypeHandler(Class<?> propertyType) {
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
public FastjsonTypeHandler(Class<?> propertyType, Class<?> genericType) {
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = genericType;
|
||||
this.type = new ParameterizedTypeImpl(propertyType, genericType);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseJson(String json) {
|
||||
if (genericType != null && Collection.class.isAssignableFrom(propertyType)) {
|
||||
return JSON.parseObject(json, type);
|
||||
} else {
|
||||
return JSON.parseObject(json, propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(Object object) {
|
||||
@ -37,4 +57,66 @@ public class FastjsonTypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
SerializerFeature.WriteNullListAsEmpty, SerializerFeature.WriteNullStringAsEmpty);
|
||||
}
|
||||
|
||||
|
||||
public static class ParameterizedTypeImpl implements ParameterizedType {
|
||||
|
||||
private final Type[] actualTypeArguments;
|
||||
private final Type ownerType;
|
||||
private final Type rawType;
|
||||
|
||||
public ParameterizedTypeImpl(Type rawType, Type... actualTypeArguments) {
|
||||
this.rawType = rawType;
|
||||
this.actualTypeArguments = actualTypeArguments;
|
||||
this.ownerType = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return this.actualTypeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return this.ownerType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return this.rawType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
} else if (o != null && this.getClass() == o.getClass()) {
|
||||
ParameterizedTypeImpl that = (ParameterizedTypeImpl) o;
|
||||
if (!Arrays.equals(this.actualTypeArguments, that.actualTypeArguments)) {
|
||||
return false;
|
||||
} else {
|
||||
if (this.ownerType != null) {
|
||||
if (this.ownerType.equals(that.ownerType)) {
|
||||
return this.rawType != null ? this.rawType.equals(that.rawType) : that.rawType == null;
|
||||
}
|
||||
} else if (that.ownerType == null) {
|
||||
return this.rawType != null ? this.rawType.equals(that.rawType) : that.rawType == null;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = this.actualTypeArguments != null ? Arrays.hashCode(this.actualTypeArguments) : 0;
|
||||
result = 31 * result + (this.ownerType != null ? this.ownerType.hashCode() : 0);
|
||||
result = 31 * result + (this.rawType != null ? this.rawType.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -16,20 +16,35 @@
|
||||
package com.mybatisflex.core.handler;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
*/
|
||||
public class GsonTypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
|
||||
private static Gson gson;
|
||||
private final Class<?> propertyType;
|
||||
private Class<?> genericType;
|
||||
|
||||
public GsonTypeHandler(Class<?> type) {
|
||||
this.propertyType = type;
|
||||
public GsonTypeHandler(Class<?> propertyType) {
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
public GsonTypeHandler(Class<?> propertyType, Class<?> genericType) {
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = genericType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseJson(String json) {
|
||||
if (genericType != null) {
|
||||
TypeToken<?> typeToken = TypeToken.getParameterized(propertyType, genericType);
|
||||
return getGson().fromJson(json, typeToken);
|
||||
} else {
|
||||
return getGson().fromJson(json, propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String toJson(Object object) {
|
||||
|
||||
@ -16,24 +16,40 @@
|
||||
package com.mybatisflex.core.handler;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.mybatisflex.core.exception.FlexExceptions;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* @author michael
|
||||
*/
|
||||
public class JacksonTypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
|
||||
private static ObjectMapper objectMapper;
|
||||
private final Class<?> propertyType;
|
||||
private Class<?> genericType;
|
||||
private JavaType javaType;
|
||||
|
||||
public JacksonTypeHandler(Class<?> propertyType) {
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
public JacksonTypeHandler(Class<?> propertyType, Class<?> genericType) {
|
||||
this.propertyType = propertyType;
|
||||
this.genericType = genericType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object parseJson(String json) {
|
||||
try {
|
||||
if (genericType != null && Collection.class.isAssignableFrom(propertyType)) {
|
||||
return getObjectMapper().readValue(json, getJavaType());
|
||||
} else {
|
||||
return getObjectMapper().readValue(json, propertyType);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw FlexExceptions.wrap(e, "Can not parseJson by JacksonTypeHandler: " + json);
|
||||
}
|
||||
@ -48,6 +64,14 @@ public class JacksonTypeHandler extends BaseJsonTypeHandler<Object> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public JavaType getJavaType() {
|
||||
if (javaType == null){
|
||||
javaType = getObjectMapper().getTypeFactory().constructCollectionType((Class<? extends Collection>) propertyType, genericType);
|
||||
}
|
||||
return javaType;
|
||||
}
|
||||
|
||||
public static ObjectMapper getObjectMapper() {
|
||||
if (null == objectMapper) {
|
||||
objectMapper = new ObjectMapper();
|
||||
|
||||
@ -27,10 +27,7 @@ import org.apache.ibatis.io.ResolverUtil;
|
||||
import org.apache.ibatis.reflection.Reflector;
|
||||
import org.apache.ibatis.reflection.TypeParameterResolver;
|
||||
import org.apache.ibatis.session.Configuration;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
import org.apache.ibatis.type.TypeHandler;
|
||||
import org.apache.ibatis.type.TypeHandlerRegistry;
|
||||
import org.apache.ibatis.type.UnknownTypeHandler;
|
||||
import org.apache.ibatis.type.*;
|
||||
import org.apache.ibatis.util.MapUtil;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
@ -310,10 +307,22 @@ public class TableInfoFactory {
|
||||
columnInfo.setPropertyType(fieldType);
|
||||
|
||||
if (column != null && column.typeHandler() != UnknownTypeHandler.class) {
|
||||
TypeHandler<?> typeHandler;
|
||||
|
||||
// 集合类型,传入泛型
|
||||
// fixed https://gitee.com/mybatis-flex/mybatis-flex/issues/I7S2YE
|
||||
if (Collection.class.isAssignableFrom(fieldType)) {
|
||||
typeHandler = createCollectionTypeHandler(entityClass, field, column.typeHandler(), fieldType);
|
||||
}
|
||||
|
||||
//非集合类型
|
||||
else {
|
||||
Class<?> typeHandlerClass = column.typeHandler();
|
||||
Configuration configuration = FlexGlobalConfig.getDefaultConfig().getConfiguration();
|
||||
TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
|
||||
TypeHandler<?> typeHandler = typeHandlerRegistry.getInstance(columnInfo.getPropertyType(), typeHandlerClass);
|
||||
typeHandler = typeHandlerRegistry.getInstance(columnInfo.getPropertyType(), typeHandlerClass);
|
||||
}
|
||||
|
||||
columnInfo.setTypeHandler(typeHandler);
|
||||
}
|
||||
|
||||
@ -359,6 +368,48 @@ public class TableInfoFactory {
|
||||
return tableInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 typeHandler
|
||||
* 参考 {@link TypeHandlerRegistry#getInstance(Class, Class)}
|
||||
*
|
||||
* @param entityClass
|
||||
* @param field
|
||||
* @param typeHandlerClass
|
||||
* @param fieldType
|
||||
*/
|
||||
private static TypeHandler<?> createCollectionTypeHandler(Class<?> entityClass, Field field, Class<?> typeHandlerClass, Class<?> fieldType) {
|
||||
Class<?> genericClass = null;
|
||||
Type genericType = TypeParameterResolver.resolveFieldType(field, entityClass);
|
||||
if (genericType instanceof ParameterizedType) {
|
||||
Type actualTypeArgument = ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||
if (actualTypeArgument instanceof Class) {
|
||||
genericClass = (Class<?>) actualTypeArgument;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
Constructor<?> constructor = typeHandlerClass.getConstructor(Class.class, Class.class);
|
||||
return (TypeHandler<?>) constructor.newInstance(fieldType, genericClass);
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
} catch (Exception e) {
|
||||
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
|
||||
}
|
||||
try {
|
||||
Constructor<?> constructor = typeHandlerClass.getConstructor(Class.class);
|
||||
return (TypeHandler<?>) constructor.newInstance(fieldType);
|
||||
} catch (NoSuchMethodException ignored) {
|
||||
} catch (Exception e) {
|
||||
throw new TypeException("Failed invoking constructor for handler " + typeHandlerClass, e);
|
||||
}
|
||||
try {
|
||||
Constructor<?> c = typeHandlerClass.getConstructor();
|
||||
return (TypeHandler<?>) c.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new TypeException("Unable to find a usable constructor for " + typeHandlerClass, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static String getColumnName(boolean isCamelToUnderline, Field field, Column column) {
|
||||
if (column != null && StringUtil.isNotBlank(column.value())) {
|
||||
return column.value();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user