• Mybatis3.3.0 Po类有LocalDateTime字段报错


      想写本文的原因是设计了一个Po类,里面有LocalDateTime,启动Mybatis就报错了,下面就分析分析为啥报错

    一 解析ResultMap的入口

       XMLMapperBuilder.configurationElement 

    private void configurationElement(XNode context) {
        try {
          String namespace = context.getStringAttribute("namespace");
          if (namespace == null || namespace.equals("")) {
            throw new BuilderException("Mapper's namespace cannot be empty");
          }
          builderAssistant.setCurrentNamespace(namespace);
          cacheRefElement(context.evalNode("cache-ref"));
          cacheElement(context.evalNode("cache"));
          parameterMapElement(context.evalNodes("/mapper/parameterMap"));
          resultMapElements(context.evalNodes("/mapper/resultMap"));
          sqlElement(context.evalNodes("/mapper/sql"));
          buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
        } catch (Exception e) {
          throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
        }
      }

      

    private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
        ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
        String id = resultMapNode.getStringAttribute("id",
            resultMapNode.getValueBasedIdentifier());
        String type = resultMapNode.getStringAttribute("type",
            resultMapNode.getStringAttribute("ofType",
                resultMapNode.getStringAttribute("resultType",
                    resultMapNode.getStringAttribute("javaType"))));
        String extend = resultMapNode.getStringAttribute("extends");
        Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
        Class<?> typeClass = resolveClass(type);
        Discriminator discriminator = null;
        List<ResultMapping> resultMappings = new ArrayList<ResultMapping>();
        resultMappings.addAll(additionalResultMappings);
        List<XNode> resultChildren = resultMapNode.getChildren();
        for (XNode resultChild : resultChildren) {//对每个字段的映射做处理
          if ("constructor".equals(resultChild.getName())) {
            processConstructorElement(resultChild, typeClass, resultMappings);
          } else if ("discriminator".equals(resultChild.getName())) {
            discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
          } else {
            List<ResultFlag> flags = new ArrayList<ResultFlag>();
            if ("id".equals(resultChild.getName())) {
              flags.add(ResultFlag.ID);
            }
            resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));//把每个属性的映射都放进一个List中
          }
        }
        ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
        try {
          return resultMapResolver.resolve();
        } catch (IncompleteElementException  e) {
          configuration.addIncompleteResultMap(resultMapResolver);
          throw e;
        }
      }

    重点分析  buildResultMappingFromContext 

      

    private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) throws Exception {
        String property = context.getStringAttribute("property");
        String column = context.getStringAttribute("column");
        String javaType = context.getStringAttribute("javaType");
        String jdbcType = context.getStringAttribute("jdbcType");
        String nestedSelect = context.getStringAttribute("select");
        String nestedResultMap = context.getStringAttribute("resultMap",
            processNestedResultMappings(context, Collections.<ResultMapping> emptyList()));
        String notNullColumn = context.getStringAttribute("notNullColumn");
        String columnPrefix = context.getStringAttribute("columnPrefix");
        String typeHandler = context.getStringAttribute("typeHandler");//如果不显示配置,这里是null
        String resulSet = context.getStringAttribute("resultSet");
        String foreignColumn = context.getStringAttribute("foreignColumn");
        boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
        Class<?> javaTypeClass = resolveClass(javaType);
        @SuppressWarnings("unchecked")
        Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
        JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
        return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resulSet, foreignColumn, lazy);
      }
    public ResultMapping buildResultMapping(
          Class<?> resultType,
          String property,
          String column,
          Class<?> javaType,
          JdbcType jdbcType,
          String nestedSelect,
          String nestedResultMap,
          String notNullColumn,
          String columnPrefix,
          Class<? extends TypeHandler<?>> typeHandler,
          List<ResultFlag> flags,
          String resultSet,
          String foreignColumn,
          boolean lazy) {
        Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
        TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
        List<ResultMapping> composites = parseCompositeColumnName(column);
        if (composites.size() > 0) {
          column = null;
        }
        ResultMapping.Builder builder = new ResultMapping.Builder(configuration, property, column, javaTypeClass);
        builder.jdbcType(jdbcType);
        builder.nestedQueryId(applyCurrentNamespace(nestedSelect, true));
        builder.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true));
        builder.resultSet(resultSet);
        builder.typeHandler(typeHandlerInstance);
        builder.flags(flags == null ? new ArrayList<ResultFlag>() : flags);
        builder.composites(composites);
        builder.notNullColumns(parseMultipleColumnNames(notNullColumn));
        builder.columnPrefix(columnPrefix);
        builder.foreignColumn(foreignColumn);
        builder.lazy(lazy);
        return builder.build();
      }

    记住,此时的 typeHandlerInstance 还是null的

    public ResultMapping build() {
          // lock down collections
          resultMapping.flags = Collections.unmodifiableList(resultMapping.flags);
          resultMapping.composites = Collections.unmodifiableList(resultMapping.composites);
          resolveTypeHandler();//这里才是解决typeHandler的核心
          validate();
          return resultMapping;
        }

    最终执行的是  TypeHandlerRegistry.getTypeHandler 

     private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {//type是String,jdbcType是Char
        Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = TYPE_HANDLER_MAP.get(type);
        TypeHandler<?> handler = null;
        if (jdbcHandlerMap != null) {
          handler = jdbcHandlerMap.get(jdbcType);
          if (handler == null) {
            handler = jdbcHandlerMap.get(null);
          }
        }
        if (handler == null && type != null && type instanceof Class && Enum.class.isAssignableFrom((Class<?>) type)) {
          handler = new EnumTypeHandler((Class<?>) type);
        }
        // type drives generics here
        return (TypeHandler<T>) handler;//最终找到的StringTypeHandler
      }

      如果是3.3.0之前的版本mybatis是没有LocalDateTime类型的,所以这里返回的handler只能是null,最终会抛出异常

      

  • 相关阅读:
    JavaScript 深入了解对象中的属性
    JavaScript 开发规范
    vue 项目接口管理
    放大镜特效
    多用户ATM机(面向对象编程)
    浏览器检查块代码
    js中innerHTML与innerText的用法与区别
    symbol访问法及symbor注册表
    最常用的15个前端表单验证JS正则表达式
    数组的遍历
  • 原文地址:https://www.cnblogs.com/juniorMa/p/13999110.html
Copyright © 2020-2023  润新知