org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

报错信息

2020-08-18 17:58:57.578 ERROR 30780 — [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.RuntimeException: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.tzq0301.springboot.mapper.StudentMapper.selectByPrimaryKey
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.tzq0301.springboot.mapper.StudentMapper.selectByPrimaryKey
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235)
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53)
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker​$0(MapperProxy.java:115)
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660)
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85)
at com.sun.proxy.​$Proxy75.selectByPrimaryKey(Unknown Source)
at cn.tzq0301.springboot.service.impl.StudentServiceImpl.getStudentById(StudentServiceImpl.java:27)
at com.alibaba.dubbo.common.bytecode.Wrapper1.invokeMethod(Wrapper1.java)
at com.alibaba.dubbo.rpc.proxy.javassist.JavassistProxyFactory​$1.doInvoke(JavassistProxyFactory.java:45)
at com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker.invoke(AbstractProxyInvoker.java:71)
at com.alibaba.dubbo.config.invoker.DelegateProviderMetaDataInvoker.invoke(DelegateProviderMetaDataInvoker.java:48)
at com.alibaba.dubbo.rpc.protocol.InvokerWrapper.invoke(InvokerWrapper.java:52)
at com.alibaba.dubbo.rpc.filter.ExceptionFilter.invoke(ExceptionFilter.java:61)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper​$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.monitor.support.MonitorFilter.invoke(MonitorFilter.java:74)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper​$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.filter.TimeoutFilter.invoke(TimeoutFilter.java:41)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper​$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.protocol.dubbo.filter.TraceFilter.invoke(TraceFilter.java:77)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.filter.ContextFilter.invoke(ContextFilter.java:71)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.filter.GenericFilter.invoke(GenericFilter.java:131)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.filter.ClassLoaderFilter.invoke(ClassLoaderFilter.java:37)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:37)
at com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:68)
at com.alibaba.dubbo.rpc.protocol.dubbo.DubboProtocol​$1.reply(DubboProtocol.java:98)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:96)
at com.alibaba.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:168)
at com.alibaba.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:50)
at com.alibaba.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:79)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
] with root cause

分析

该报错是 ibatis 的 BindingException,简而言之是 mapper接口 与 mapper.xml配置文件绑定失败。

解决方案

在 SpringBoot 的核心配置文件中加入以下代码:

mybatis.mapper-locations=classpath:mapper/*.xml

用于指定 mapper.xml 配置文件的位置。

可能造成 BindingException 的几种错误原因

下列所有 “mapper” 都可以被 “dao” 代替,命名方式因人而异

  1. 未在配置文件中指定 xxxMapper.xml DAO配置文件的位置;

  2. 将 mybatis.mapper-locations 误写成 mybatis.config-location 等其他配置;

  3. 类似名为 xxxMapper.java 的接口 interface 上未写 @Mapper 注解,导致容器无法将此类识别为 mapper 类;

  4. Spring Boot 启动类 application.java 上未写 @MapperScan 注解,导致容器无法扫描 mapper 文件;

  5. 在编译阶段,项目未将 xxxMapper.xml 加入到 target 文件夹下,对于该问题,有两种情况,或称有两种解决办法:

    • 你将 xxxMapper.xml 配置文件放置在 src/main/java/com.xxx.mapper 包中:

      建议将该文件放置在 src/main/resources 目录下,该目录才是存放资源文件的正确位置。

      接下来的解决方案请参考下文。

    • 你将 xxxMapper.xml 配置文件放置在 src/main/resources 目录下:

      通常你的 src/main/resources 目录下的 xml 文件都会在编译阶段被自动导入到 target 文件夹下,但你可能在 pom.xml 文件中,对 <resources> 标签进行了自定义(若 <resources> 标签未被自定义,Maven工程项目会默认将 resources 资源文件夹下的所有文件导入到 target 文件夹下;但若是你对 <resources> 标签进行了自定义,该 “默认方案” 将会无效,并且将按照你指定的方案进行导入。)

      例如,你之前因为将 xxxMapper.xml 配置文件放置在 src/main/java目录下,所以对 <resources> 标签做了如下修改:

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

      这将是 src/main/java 目录下所有的文件都导入到 target 文件夹下的操作,如果你的 <resources> 标签中只有这些东西,那么你的 src/main/resources 目录下的所有文件都不会被导入到 target 文件夹,若你想要保留这个操作且让 src/main/resources 目录下的所有文件都被导入到 target 文件夹下,你可以将其修改为:

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

      但这还是比较繁琐的。

      最简单的方式就是:将所有配置文件( xxxMapper.xml 等)放置在 src/main/resources 目录下,并不要添加 <resources> 标签并对其进行自定义(即采用Maven工程的默认导入方案,详见上文)即可。

      这种方式是最符合项目结构的方式,且最简洁。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐