Fameya 2023-11-21 00:51 采纳率: 0%
浏览 21

Javaweb入门案例报错,

img

img

img

img

这里报错是因为什么啊,对照网上的代码半天都没有找出来,是不是 config 和 mapper 不匹配啊?

刚开始 SqlSessionFactoryBuilder 爆红,导入包但是写代码的时候不自动提示,写完爆红

  • 写回答

3条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-11-21 02:25
    关注

    【相关推荐】



    • 这篇博客: 1、SqlSessionFactoryBean的创建-1中的 5.2.1 mapper文件个元素的解析 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
      private void configurationElement(XNode context) {
          try {
            //获取mapper标签上的namespace属性
            String namespace = context.getStringAttribute("namespace");
            if (namespace == null || namespace.equals("")) {
              throw new BuilderException("Mapper's namespace cannot be empty");
            }
            //设置namespace到构建助手类中
            builderAssistant.setCurrentNamespace(namespace);
            //解析cache-ref标签
            cacheRefElement(context.evalNode("cache-ref"));
            //解析cache
            cacheElement(context.evalNode("cache"));
            //解析parameterMap,这种方式已经过时,不建议在使用
            parameterMapElement(context.evalNodes("/mapper/parameterMap"));
            //解析resultMap
            resultMapElements(context.evalNodes("/mapper/resultMap"));
            //解析sql片段
            sqlElement(context.evalNodes("/mapper/sql"));
            //解析select,insert,update,delete
            buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
          } catch (Exception e) {
            throw new BuilderException("Error parsing Mapper XML. Cause: " + e, e);
          }
        }
      
      1. 解析cache-ref标签
      private void cacheRefElement(XNode context) {
          if (context != null) {
            //cacheRefMap.put(namespace, referencedNamespace);
            configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
            /* public CacheRefResolver(MapperBuilderAssistant assistant, String cacheRefNamespace) {
             *    this.assistant = assistant;
             *    this.cacheRefNamespace = cacheRefNamespace;
             * }
             */
            CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
            try {
              //解析缓存引用
              //(*1*)
              cacheRefResolver.resolveCacheRef();
            } catch (IncompleteElementException e) {
              //如果解析失败,那么存放到待解析列表,等所有解析结束之后再次解析
              configuration.addIncompleteCacheRef(cacheRefResolver);
            }
          }
        }
        
        //(*1*)
        public Cache CacheRefResolver.resolveCacheRef() {
          //(*2*)
          return assistant.useCacheRef(cacheRefNamespace);
        }
        
        //(*2*)
        public Cache org.apache.ibatis.builder.MapperBuilderAssistant.useCacheRef(String namespace) {
          if (namespace == null) {
            throw new BuilderException("cache-ref element requires a namespace attribute.");
          }
          try {
            unresolvedCacheRef = true;
            //从configuration的Map<String, Cache> caches中获取值
            Cache cache = configuration.getCache(namespace);
            if (cache == null) {
              //解析失败
              throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
            }
            currentCache = cache;
            unresolvedCacheRef = false;
            return cache;
          } catch (IllegalArgumentException e) {
            throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
          }
        }
      
      1. 解析cache
      private void org.apache.ibatis.builder.xml.XMLMapperBuilder.cacheElement(XNode context) throws Exception {
          if (context != null) {
            //获取缓存对象类型,如果没有设置,那么默认为PERPETUAL
            String type = context.getStringAttribute("type", "PERPETUAL");
            //解析别名
            Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
            //设置缓存策略:最近使用原则
            String eviction = context.getStringAttribute("eviction", "LRU");
            //获取LRU策略
            Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
            //获取刷新频率
            Long flushInterval = context.getLongAttribute("flushInterval");
            //获取缓存大小
            Integer size = context.getIntAttribute("size");
            //是否只读
            boolean readWrite = !context.getBooleanAttribute("readOnly", false);
            //是否阻塞
            boolean blocking = context.getBooleanAttribute("blocking", false);
            //获取缓存配置属性
            Properties props = context.getChildrenAsProperties();
            //设置缓存
            //(*1*)
            builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
          }
        }
        
        //(*1*)
        public Cache org.apache.ibatis.builder.MapperBuilderAssistant.useNewCache(Class<? extends Cache> typeClass,
            Class<? extends Cache> evictionClass,
            Long flushInterval,
            Integer size,
            boolean readWrite,
            boolean blocking,
            Properties props) {
          //CacheCacheBuilder(缓存建造器)
          Cache cache = new CacheBuilder(currentNamespace)
              //valueOrDefault在第一个参数值为null的时候会使用第二个参数,PerpetualCache为默认的缓存实现
              .implementation(valueOrDefault(typeClass, PerpetualCache.class))
              //设置装饰器,默认LruCache
              .addDecorator(valueOrDefault(evictionClass, LruCache.class))
              .clearInterval(flushInterval)
              .size(size)
              .readWrite(readWrite)
              .blocking(blocking)
              .properties(props)
              .build();
          //namespace -》 cache对象
          configuration.addCache(cache);
          //org.apache.ibatis.builder.MapperBuilderAssistant.currentCache = cache
          currentCache = cache;
          return cache;
        }
        
        //缓存对象的构建
        public Cache org.apache.ibatis.mapping.CacheBuilder.build() {
          //确保有Cache的实现类,如果没有定义,那么设置的将是PerpetualCache
          setDefaultImplementations();
          //寻找缓存的构造器,其构造参数为String,也就是用于传递namespace的参数
          Cache cache = newBaseCacheInstance(implementation, id);
          //设置属性,这个属性就是在cache标签下面设置的property标签
          setCacheProperties(cache);
          // issue #352, do not apply decorators to custom caches
          //如果是mybatis的缓存就进行装饰,自定义的缓存只会被LoggingCache装饰
          if (PerpetualCache.class.equals(cache.getClass())) {
            for (Class<? extends Cache> decorator : decorators) {
              cache = newCacheDecoratorInstance(decorator, cache);
              //设置属性
              setCacheProperties(cache);
            }
            //使用标准的装饰器进行装饰,比如根据是否设置了clearInterval,用ScheduledCache进行装饰
            cache = setStandardDecorators(cache);
          } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
            cache = new LoggingCache(cache);
          }
          return cache;
        }
      
      1. 解析parameterMap(已过时,这类信息都由#{}表达式代替)
      //  /mapper/parameterMap
      private void org.apache.ibatis.builder.xml.XMLMapperBuilder.parameterMapElement(List<XNode> list) throws Exception {
          for (XNode parameterMapNode : list) {
            //解析parameterMap的id属性
            String id = parameterMapNode.getStringAttribute("id");
            //解析参数类型
            String type = parameterMapNode.getStringAttribute("type");
            //解析参数class对象
            Class<?> parameterClass = resolveClass(type);
            //获取parameter标签
            List<XNode> parameterNodes = parameterMapNode.evalNodes("parameter");
            List<ParameterMapping> parameterMappings = new ArrayList<ParameterMapping>();
            for (XNode parameterNode : parameterNodes) {
              //属性名
              String property = parameterNode.getStringAttribute("property");
              //java类型
              String javaType = parameterNode.getStringAttribute("javaType");
              //jdbc类型
              String jdbcType = parameterNode.getStringAttribute("jdbcType");
              //resultMap,sql返回值映射,通常配置了parameterMap属性的select标签什么的,不需要再配置
              //resultMap,resultType,parameterType
              String resultMap = parameterNode.getStringAttribute("resultMap");
              //模式,比如IN,OUT,INOUT
              String mode = parameterNode.getStringAttribute("mode");
              //类型处理器
              String typeHandler = parameterNode.getStringAttribute("typeHandler");
              //小数位
              Integer numericScale = parameterNode.getIntAttribute("numericScale");
              //解析参数模式ParameterMode.IN, ParameterMode.OUT,ParameterMode.INOUT
              ParameterMode modeEnum = resolveParameterMode(mode);
              //解析java类型
              Class<?> javaTypeClass = resolveClass(javaType);
              //jdbc类型
              JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
              @SuppressWarnings("unchecked")
              //解析类型处理器
              Class<? extends TypeHandler<?>> typeHandlerClass = (Class<? extends TypeHandler<?>>) resolveClass(typeHandler);
              //构建ParameterMapping
              //(*1*)
              ParameterMapping parameterMapping = builderAssistant.buildParameterMapping(parameterClass, property, javaTypeClass, jdbcTypeEnum, resultMap, modeEnum, typeHandlerClass, numericScale);
              parameterMappings.add(parameterMapping);
            }
            builderAssistant.addParameterMap(id, parameterClass, parameterMappings);
          }
        }
        
        //(*1*)
         public ParameterMapping buildParameterMapping(
            Class<?> parameterType,
            String property,
            Class<?> javaType,
            JdbcType jdbcType,
            String resultMap,
            ParameterMode parameterMode,
            Class<? extends TypeHandler<?>> typeHandler,
            Integer numericScale) {
          //拼接namespace =》 namespace + "." + resultMap
          resultMap = applyCurrentNamespace(resultMap, true);
      
          // Class parameterType = parameterMapBuilder.type();
          //如果javaType类型为空,那么进行解析,通常会使用MetaClass进行反射
          Class<?> javaTypeClass = resolveParameterJavaType(parameterType, property, javaType, jdbcType);
          //如果没有提供typeHandler,那么从typeHandler注册中获取
          TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
          //构建参数map
          return new ParameterMapping.Builder(configuration, property, javaTypeClass)
              .jdbcType(jdbcType)
              .resultMapId(resultMap)
              .mode(parameterMode)
              .numericScale(numericScale)
              .typeHandler(typeHandlerInstance)
              //构建,在返回之前,如果typeHandler依然为空,会继续从typeHandler注册器中获取
              //校验,eg:如果参数类型为ResultSet,那么resultMap必须存在
              .build();
        }
      
      1. 解析resultMap
      private void org.apache.ibatis.builder.xml.XMLMapperBuilder.resultMapElements(List<XNode> list) throws Exception {
          for (XNode resultMapNode : list) {
            try {
              resultMapElement(resultMapNode);
            } catch (IncompleteElementException e) {
              // ignore, it will be retried
            }
          }
        }
        
        private ResultMap resultMapElement(XNode resultMapNode) throws Exception {
          return resultMapElement(resultMapNode, Collections.<ResultMapping> emptyList());
        }
        //resultMap节点解析
        private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings) throws Exception {
          ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
          //获取resultMap节点属性id,如果没有那么使用默认的 resultMapNode.getValueBasedIdentifier()
          String id = resultMapNode.getStringAttribute("id",
              resultMapNode.getValueBasedIdentifier());
          //获取返回值类型
          String type = resultMapNode.getStringAttribute("type",
              resultMapNode.getStringAttribute("ofType",
                  resultMapNode.getStringAttribute("resultType",
                      resultMapNode.getStringAttribute("javaType"))));
          //获取继承的ResultMap配置id
          String extend = resultMapNode.getStringAttribute("extends");
          //是否自动映射,自动映射将采用反射的方式进行映射
          Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
          //解析成javaType
          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);
              }
              //构建resultMap
              resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
            }
          }
          ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
          try {
              //解析
            return resultMapResolver.resolve();
          } catch (IncompleteElementException  e) {
            configuration.addIncompleteResultMap(resultMapResolver);
            throw e;
          }
        }
      

    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论
  • 酷爱码 2023-11-21 07:32
    关注

    xml文件一般不提示,估计你是漏了闭合标签或者多加少写>

    评论
  • 关注

    第二张图不要分号,第三张图完整代码贴出来,应该是你xml写错了

    评论

报告相同问题?

问题事件

  • 创建了问题 11月21日

悬赏问题

  • ¥30 哈夫曼编码译码器打印树形项目
  • ¥20 求完整顺利登陆QQ邮箱的python代码
  • ¥15 怎么下载MySQL,怎么卸干净原来的MySQL
  • ¥15 网络打印机Ip地址自动获取出现问题
  • ¥15 求局部放电案例库,用于预测局部放电类型
  • ¥100 QT Open62541
  • ¥15 stata合并季度数据和日度数据
  • ¥15 谁能提供rabbitmq,erlang,socat压缩包,记住版本要对应
  • ¥15 Vue3 中使用 `vue-router` 只能跳转到主页面?
  • ¥15 用QT,进行QGIS二次开发,如何在添加栅格图层时,将黑白的矢量图渲染成彩色