MyBatis测试报错:Cannot determine value type from string 'xxx'的解决办法

 更新时间:2023年02月17日 09:16:35   作者:大先生哈哈哈  
这篇文章主要给大家介绍了关于MyBatis测试报错:Cannot determine value type from string 'xxx'的解决办法,文中通过实例代码介绍的非常详细,需要的朋友可以参考下

关于[Cannot determine value type from string ‘xxx’]的问题

1、产生

实体类Student中属性有id,name,email,age,未使用无参构造器

在mapper.xml中只查询name,email,age

测试时报错

Cannot determine value type from string '张三'

2、解决

实体类Student中添加无参构造器

得到结果

Student{id=null, name='张三', email='zhangsan@126.com', age=22}

3、探究

跟踪源码

org.apache.ibatis.executor.resultset.DefaultResultSetHandler

这个类有个方法createResultObject

private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, String columnPrefix)
      throws SQLException {
    final Class<?> resultType = resultMap.getType();
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    } else if (!constructorMappings.isEmpty()) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs, columnPrefix);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      return createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs);
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }

这个方法是根据结果集返回值的类型创建出相应的bean字段对象

  • 当实体使用无参构造器时

mybatis会调用createResultObject方法中objectFactory.create(resultType),使用无参构造器创建对象

private  <T> T instantiateClass(Class<T> type, List<Class<?>> constructorArgTypes, List<Object> constructorArgs) {
    try {
      Constructor<T> constructor;
      if (constructorArgTypes == null || constructorArgs == null) {
        constructor = type.getDeclaredConstructor();
        try {
          return constructor.newInstance();
        } catch (IllegalAccessException e) {
          if (Reflector.canControlMemberAccessible()) {
            constructor.setAccessible(true);
            return constructor.newInstance();
          } else {
            throw e;
          }
        }
      }
      constructor = type.getDeclaredConstructor(constructorArgTypes.toArray(new Class[0]));
      try {
        return constructor.newInstance(constructorArgs.toArray(new Object[0]));
      } catch (IllegalAccessException e) {
        if (Reflector.canControlMemberAccessible()) {
          constructor.setAccessible(true);
          return constructor.newInstance(constructorArgs.toArray(new Object[0]));
        } else {
          throw e;
        }
      }
    } catch (Exception e) {
      String argTypes = Optional.ofNullable(constructorArgTypes).orElseGet(Collections::emptyList)
          .stream().map(Class::getSimpleName).collect(Collectors.joining(","));
      String argValues = Optional.ofNullable(constructorArgs).orElseGet(Collections::emptyList)
          .stream().map(String::valueOf).collect(Collectors.joining(","));
      throw new ReflectionException("Error instantiating " + type + " with invalid types (" + argTypes + ") or values (" + argValues + "). Cause: " + e, e);
    }
  }

当实体使用有参构造参数

mybatis会调用createResultObject方法中createByConstructorSignature(rsw, resultType, constructorArgTypes, constructorArgs);

private Object createUsingConstructor(ResultSetWrapper rsw, Class<?> resultType, List<Class<?>> constructorArgTypes, List<Object> constructorArgs, Constructor<?> constructor) throws SQLException {
    boolean foundValues = false;
    for (int i = 0; i < constructor.getParameterTypes().length; i++) {
      Class<?> parameterType = constructor.getParameterTypes()[i];
      String columnName = rsw.getColumnNames().get(i);
      TypeHandler<?> typeHandler = rsw.getTypeHandler(parameterType, columnName);
      Object value = typeHandler.getResult(rsw.getResultSet(), columnName);
      constructorArgTypes.add(parameterType);
      constructorArgs.add(value);
      foundValues = value != null || foundValues;
    }
    return foundValues ? objectFactory.create(resultType, constructorArgTypes, constructorArgs) : null;
  }

​ 这个代码片段里面有个TypeHandler,这个是mybatis的类型处理器,用来处理 JavaType 与 JdbcType 之间的转换。

由代码我们看出,当实体使用有参构造函数时,会遍历有参构造参数个数,根据有参构造参数下标 查找相应的数据库字段名称,根据有参构造字段类型以及数据库字段名称找类型处理器。然后使用TypeHandler来处理JavaType 与 JdbcType 之间的转换。当转换异常,就会报错

4、总结

解决Cannot determine value type from string 'xxx’的方法有2种

  • 实体加无参构造参数
  • mapper.xml中查询的数据库字段属性的类型要和有参构造器的字段类型一一匹配;查询字段的个数要和有参构造器个数一样

到此这篇关于MyBatis测试报错:Cannot determine value type from string 'xxx'解决的文章就介绍到这了,更多相关Cannot determine value type from string内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java获取Process子进程进程ID方法详解

    Java获取Process子进程进程ID方法详解

    这篇文章主要介绍了Java获取Process子进程进程ID方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • springboot对数据库密码加密的实现

    springboot对数据库密码加密的实现

    这篇文章主要介绍了springboot对数据库密码加密的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12
  • Java对称加密工作模式原理详解

    Java对称加密工作模式原理详解

    这篇文章主要介绍了Java对称加密工作模式原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • uploadify java实现多文件上传和预览

    uploadify java实现多文件上传和预览

    这篇文章主要为大家详细介绍了java结合uploadify实现多文件上传和预览的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • SpringBoot集成SSM、Dubbo、Redis、JSP的案例小结及思路讲解

    SpringBoot集成SSM、Dubbo、Redis、JSP的案例小结及思路讲解

    这个案例其实就是SpringBoot集成SSM、Dubbo、Redis、JSP,看起来感觉很繁琐,其实就是很简单,下面通过案例分析给大家讲解,感兴趣的朋友跟随小编一起看看吧
    2021-05-05
  • 浅谈SpringMVC的执行流程

    浅谈SpringMVC的执行流程

    下面小编就为大家带来一篇浅谈SpringMVC的执行流程。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 关于ReentrantLock的实现原理解读

    关于ReentrantLock的实现原理解读

    这篇文章主要介绍了关于ReentrantLock的实现原理,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • Spring Boot配置元数据方法教程

    Spring Boot配置元数据方法教程

    这篇文章主要介绍了Spring Boot配置元数据方法教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • java获取注册ip实例

    java获取注册ip实例

    本文分享了java获取注册ip实例代码,代码简洁,具有很好的参考价值,需要的朋友一起来看下吧
    2016-12-12
  • java实现幸运抽奖功能

    java实现幸运抽奖功能

    这篇文章主要为大家详细介绍了java实现幸运抽奖功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03

最新评论