org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)异常处理

一、问题描述
在做spring cloud微服务项目开发时,在进行其中一个微服务启动时,先是出现如下异常信息:

java.io.FileNotFoundException: class path resource [mapper/] cannot be resolved to URL because it does not exist
    at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187)
    at org.springframework.core.io.support.PathMatchingResourcePatternResolver.findPathMatchingResources(PathMatchingResourcePatternResolver.java:464)
    at org.springframework.core.io.support.PathMatchingResourcePatternResolver.getResources(PathMatchingResourcePatternResolver.java:293)
    at org.NumberRecovery.utils.MyBatisConfig.sqlSessionFactory(MyBatisConfig.java:57)
    at org.NumberRecovery.utils.MyBatisConfig$$EnhancerBySpringCGLIB$$6977a288.CGLIB$sqlSessionFactory$1(<generated>)
    at org.NumberRecovery.utils.MyBatisConfig$$EnhancerBySpringCGLIB$$6977a288$$FastClassBySpringCGLIB$$d8fb1cdb.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:358)
    at org.NumberRecovery.utils.MyBatisConfig$$EnhancerBySpringCGLIB$$6977a288.sqlSessionFactory(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:162)

网络搜索相关解决方案后,修改application.properties配置文件中mybatis.mapperLocations=classpath:mapper/*.xml

mybatis.mapperLocations=classpath*:mapper/*.xml
(我的用来存放mapper.xml文件的mapper目录直接放到src/main/resources目录下),暂时解决,相关原因可以搜索classpath*与classpath区别的相关文章或博客
但再次启动程序,又出现如下异常信息:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): org.NumberRecovery.dao.NumberMapper.qryLockNumber
    at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:225)
    at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:48)
    at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:65)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
    at com.sun.proxy.$Proxy99.qryLockNumber(Unknown Source)
    at org.NumberRecovery.service.RecoveryService.qryLockNumber(RecoveryService.java:24)
    at org.NumberRecovery.service.RecoveryService$$FastClassBySpringCGLIB$$dc43da81.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
    at org.NumberRecovery.service.RecoveryService$$EnhancerBySpringCGLIB$$b33476fe.qryLockNumber(<generated>)
    at org.NumberRecovery.controller.RecoveryController.updateLockNumber(RecoveryController.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

二、问题解决

出现异常后,就开始了漫长的网络搜索解决方案之旅,可以查到很多这种异常的相关博客或说明,但基本内容都差不多,我这里先列举一下,前面五条可能原因不是我自己总结出来的,这里只是添加一下我自己的实际经验,然后加上我自己解决时遇到的问题,通常可能导致这个异常出现的原因有以下几种:

(1) mapper接口类和mapper.xml是否在同一个包下,文件名称是否一致(仅后缀不同):经过实际检验,这个并不需要在同一个包下面,通常mapper.xml文件是存放在src/main/resources目录下,而mapper接口类是在src/main/java目录下面;名称是否相同也不重要,我的命名分贝为NumberDao.java和NumberMapper.xml,实际也可以运行成功
(2)mapper.xml的namespace是否是对应接口类的全名(包括包名和类名):这个是必须要保证相同,需要进行检查,而且全类名最好通过复制,不要自己手动拼写,容易出错
(3)mapper接口类的方法名是否与mapper.xml中sql标签的id相同:这个也需要进行检查,必须保证一致
(4)mapper.xml文件中用resultMap,而不用resultType(当sql操作结果是List或其他复杂结果集时):我经过实践检验,我的查询结果是一个Integer的List集合,用resultMap反而报错,异常信息如下:

org.apache.ibatis.builder.IncompleteElementException: Could not find result map java.lang.Integer
    at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:346)
    at org.apache.ibatis.builder.MapperBuilderAssistant.addMappedStatement(MapperBuilderAssistant.java:290)
    at org.apache.ibatis.builder.xml.XMLStatementBuilder.parseStatementNode(XMLStatementBuilder.java:109)
    at org.apache.ibatis.session.Configuration.buildAllStatements(Configuration.java:788)
    at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:758)
    at org.apache.ibatis.session.Configuration.hasStatement(Configuration.java:753)
    at org.apache.ibatis.binding.MapperMethod$SqlCommand.resolveMappedStatement(MapperMethod.java:247)
    at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:217)
    at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:48)
    at org.apache.ibatis.binding.MapperProxy.cachedMapperMethod(MapperProxy.java:65)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:58)
    at com.sun.proxy.$Proxy99.qryLockNumber(Unknown Source)
    at org.NumberRecovery.service.RecoveryService.qryLockNumber(RecoveryService.java:23)
    at org.NumberRecovery.service.RecoveryService$$FastClassBySpringCGLIB$$dc43da81.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:738)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
    at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:673)
    at org.NumberRecovery.service.RecoveryService$$EnhancerBySpringCGLIB$$a9c68bd2.qryLockNumber(<generated>)
    at org.NumberRecovery.controller.RecoveryController.updateLockNumber(RecoveryController.java:39)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.scheduling.support.ScheduledMethodRunnable.run(ScheduledMethodRunnable.java:65)
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
    at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source)
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: Result Maps collection does not contain value for java.lang.Integer
    at org.apache.ibatis.session.Configuration$StrictMap.get(Configuration.java:888)
    at org.apache.ibatis.session.Configuration.getResultMap(Configuration.java:640)
    at org.apache.ibatis.builder.MapperBuilderAssistant.getStatementResultMaps(MapperBuilderAssistant.java:344)
    ... 36 common frames omitted

(5) 到target目录下看是否有mapper.xml文件生成(按照自己对mapper.xml文件的路径配置到target下classes目录下找),如果没有可以在pom.xml文件的<build></build>之间添加

<resources>
     <resource>
          <directory>src/main/resources</directory>
          <includes>
              <include>**/*.xml</include>
          </includes>
     </resource>
 </resources>

也可以再在<resources></resources>之间再添加一项

<resource>
    <directory>src/main/java</directory>
    <includes>
        <include>**/*.xml</include>
    </includes>
</resource>

使mapper.xml文件不论是放在src/main/resourcessrc/main/java下都可以被打包到classes目录下。

(6)前面几项的可能原因都是我从网络上查找到的,做了所有的修改和检查,也没有解决问题,然后发现我要说明的这最后一项才是我这次遇到的问题,这个经历非常坑,完全没有考虑到出现这次的问题的情况,用了我整整一天加一晚上的时间……..非常无语。
就是我的项目代码最开始是在我这里开发的,组内另外一名同事用的是IDEA开发,他在向git上提交时,把一个.idea的目录也上传到git上(没用过IDEA,不清楚这个目录的作用)。我checkout到本地后,发现出现上述异常,怎么都改不好。最后我在本地删除了.idea目录,然后程序居然正常运行起来了,正常运行起来了,正常运行起来了!!!!!!
怎么也没想到是因为两个IDE之间还会有这种影响,还是经验不足,对其他的IDE了解不到位造成用了这么多时间都没有解决问题。。。。。。


经过此次问题解决,必须得写下来作为文字记录这个过程和解决问题的原因!防止以后再次遇到这种问题束手无策!同时也可以给其他遇到这个问题的小伙伴儿提供一个可能的解决问题的方向。

  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值