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

Posted 大先生哈哈哈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于[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中添加无参构造器

得到结果

Studentid=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种

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

报错Cannot determine embedded database driver class for database type NONE解决方法

由于我不需要数据库,启动springboot报错:

Cannot determine embedded database driver class for database type NONE
If you want an embedded database please put a supported one on the classpath.
If you have database settings to be loaded from a particular profile
you may need to active it (no profiles are currently active).

删掉pom里全部相关数据库的jar,也exclude相关DataSource的class,都不能解决,报错依旧。最后:

pom增加:

    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
    </dependency>

完整的:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <!-- Cannot determine embedded database driver class for database type 
            NONE 不需要调用数据源解决方法 -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
        </dependency>
    </dependencies>

注意:参考了以下网址方法,但并不能解决问题。
https://blog.csdn.net/hengyunabc/article/details/78762097





以上是关于关于[Cannot determine value type from string ‘xxx‘]的一些问题的主要内容,如果未能解决你的问题,请参考以下文章