当有需要将Map的字段一一赋值到实体类时,发现一个一个字段取值和赋值操作比较繁琐,如果Map中数据类型不一致,还需要做类型强转。所以通过反射自动把Map的数据转成实体类中,可以让业务代码更加美观。
public static <T> T mapToEntity(Map<?, ?> map, Class<T> clazz) {
// 验证Map和实体类Class对象是否为空
(map, "map cannot be null");
(clazz, "entity class cannot be null");
try {
List<Field> allFields = new ArrayList<>();
T t = ();
Class<?> aClass = clazz;
do {
// 利用Java反射获取自身属性以及父类属性
((()).collect(()));
aClass = ();
// Object类为超级大类,到了Object类,继承关系已到了顶点,不需要处理了
} while (!((), ()));
// 对实体类的属性进行遍历
for (Field field : allFields) {
// 获取属性名称
String fieldName = ();
// 属性对应的实体类名称,这里需要一一对应,否则取不到值
Object data = (fieldName);
// 按照Java约定的getter、setter方法命名规范,拼装setter方法名
String methodName = ("set{}{}", (0, 1).toUpperCase(), (1));
// 获取setter方法的Method对象
Method method = (methodName, ());
// 利用Java反射调用实体对象的setter方法对属性进行赋值操作
(t, getData(data, ()));
}
return t;
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* 这里的这个方法是为了兼容Sql语句查询后返回的Map。
* 在使用Mybatis查询后返回的数据类型为了兼容都使用了大类型,本来是int类型的数据
* 但还是返回了long类型,在这里就做了特殊处理,如果实体类中属性为int,Map中类型为Long时,
* 就对类型进行转换。在这里还可以做其他的兼容处理
*/
private static Object getData(Object data, Class<?> type) {
String typeName = ();
if ((typeName, ())) {
if (data instanceof Long) {
return ((Long) data).intValue();
}
}
return data;
}