当前位置:主页 > java教程 > Cannot determine value type from string

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

发布:2023-04-01 09:30:01 59


给寻找编程代码教程的朋友们精选了相关的编程文章,网友麴昭昭根据主题投稿了本篇教程内容,涉及到mybatis、测试报错、mybatis报错、Cannot determine value type from string相关内容,已被927网友关注,下面的电子资料对本篇知识点有更加详尽的解释。

Cannot determine value type from string

关于[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内容请搜索码农之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持码农之家!


参考资料

相关文章

  • 解决mybatisplus MetaObjectHandler 失效的问题

    发布:2023-04-14

    本文主要介绍了解决mybatisplus MetaObjectHandler 失效的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • 如何批量测试Mybatis项目中的Sql是否正确详解

    如何批量测试Mybatis项目中的Sql是否正确详解

    发布:2022-06-17

    给大家整理了关于Mybatis的教程,这篇文章主要给大家介绍了关于如何批量测试Mybatis项目中Sql是否正确的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着


  • MyBatis SqlSource源码示例解析

    发布:2023-04-06

    这篇文章主要为大家介绍了MyBatis SqlSource源码示例解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪


  • SpringBoot+Mybatis+Vue 实现商品模块的crud操作

    SpringBoot+Mybatis+Vue 实现商品模块的crud操作

    发布:2023-01-09

    给网友朋友们带来一篇关于SpringBoot的教程,这篇文章主要介绍了SpringBoot+Mybatis+Vue 实现商品模块的crud操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • Mybatis特殊字符转义查询实现

    发布:2023-04-13

    本文主要介绍了Mybatis特殊字符转义查询实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • mybatis使用Integer类型查询可能出现的问题

    发布:2022-10-20

    给网友朋友们带来一篇关于mybatis的教程,这篇文章主要介绍了mybatis使用Integer类型查询可能出现的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教


  • 深入理解Mybatis分页插件使用方法

    发布:2020-02-29

    这篇文章主要为大家详细介绍了Mybatis分页插件的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下


  • 解读springboot配置mybatis的sql执行超时时间(mysql)

    发布:2023-03-08

    这篇文章主要介绍了解读springboot配置mybatis的sql执行超时时间(mysql),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教


网友讨论