六
本篇旨在记录最近在使用Spring Boot整合Mybatis时,因为配置不当而出现的问题,以及该问题的解决方案
对于急于寻求解决方案的小伙伴,请直接跳过中间的一大段废话,转到本篇的末尾,那里列举了两种解决方案
首先,问题报错如下:
2020-08-05 01:20:00.270 ERROR 16156 --- [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 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.gavin.mapper.PersonMapper.selectPerson] with root cause
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.gavin.mapper.PersonMapper.selectPerson
at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperMethod.<init>(MapperMethod.java:53) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperProxy.lambda$cachedInvoker$0(MapperProxy.java:115) ~[mybatis-3.5.5.jar:3.5.5]
at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_251]
at org.apache.ibatis.binding.MapperProxy.cachedInvoker(MapperProxy.java:102) ~[mybatis-3.5.5.jar:3.5.5]
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:85) ~[mybatis-3.5.5.jar:3.5.5]
.......
.......
这个问题,首先从括号的not found中就能看出来,肯定是后面的内容找不到,所以我的解决方法如下:1、首先去对应的XML文件中仔细核对了这个方法,确定方法名没写错,能找到;
2、然后我又尝试调用了其他的一些方法,结果是:这个XML中的所有SQL都找不到;那么很明显,整个XML文件都无法被找到;
3、接着,检查namespace中对应的值是否正确,依然正确,在IDEA中可以直接点进去。
这三步操作结束之后,我内心的感觉:一顿操作猛如虎,一看战绩0—5。细节方面都是对的,也没有犯哪些低级错误啊。
接下来,我又想起了我在pom.xml文件中引入mybatis相关包之后在applicationContext.yaml文件中对于mybatis的配置,配置如下:
mybatis:
mapper-locations: classpath:mapper/**.xml
type-aliases-package: com.gavin.entity
这两个配置,mapper-locations对应的SQL映射XML文件,type-aliases-package代表实体类所在的包
然后我又看了一下我的文件的位置
图①
没什么问题啊,在以前的项目中,yaml文件中也是这么配置的,xml文件的位置也是和接口放在同一个包下的,那么问题出在哪里?
好吧,面向百度编程开始:在网上搜索了很多Spring Boot整合mybatis的帖子,功夫不负有心人,很多Javar在整合mybatis的时候,都会在项目的resources路径下创建一个mapper文件夹,然后将PersonMapper.xml文件放在resources文件夹下的mapper文件夹下,恍然大悟,我们在使用maven构建项目的时候,resources目录就是classpath呀;然后我也尝试了一下:
图②
启动项目——>访问路径——>访问成功
OK,这个方法是行得通的。
那么问题来了,为什么在以前的项目中,我并没有在resources目录下看到这个文件夹,而且mapper.xml和mapper接口都是放在同一个文件下的,项目却可以正常访问,这是为何?
带着这个疑问,我打开了以前的代码,详细的阅读了相关配置;最终,在pom.xml中,看到了这样一段代码:
图③
眼前一亮,很明显,这一段代码就是解决的找不到方法声明的错误的方法!
拷贝——>测试——>OK,没问题
我在上面说过,当我们使用maven构建项目时,项目的classpath默认指向resources目录,所以可以通过在resources目录下新建一个mapper目录,用来存放我们的mapper映射文件;
对于上图中的代码,我个人的理解是:通过手动配置将我们src/main/java目录下以.xml结尾的文件及其所在文件夹,都包含进resources目录下;
这样,当SpringBoot启动器在加载yaml文件中的mybatis配置信息时,会根据classpath去resources目录下进行扫描,这时resources目录经过上述配置之后,已经包含了src/main/java目录下的.xml文件与其所对应的文件夹,所以IOC容器能够获取到我们在resources文件夹之外的mapper.xml文件。
当然以上只是我的个人理解,如果对此有不同理解的小伙伴,拜托在评论区中留下看法,让我认识到自己理解的错误,也避免其他小伙伴踩坑;
图③中的代码,是之前的老大在带领我们第一次学习使用Spring Boot来进行项目开发时写下的代码,那时候他就已经对这个问题进行了处理,而我一直没有认真阅读过这些配置,对此,深感愧疚,改之!
以上就是本人对于 Invalid bound statement (not found) 错误的解决过程和方案;
两个方法:
一个是不用改配置,在resources目录下创建mapper文件夹,然后将所有的mapper映射文件放到这个目录下;
另一个是在pom.xml文件中添加如下代码:
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
这两种方式都可以解决这个错误,诸君随意选择。