mybatis Invalid bound statement(not found)排坑记录
作者:heling_m6ss
背景
之前帮同事解决mybatis Invalid bound statement (not found):这个问题,最近看到很多人也遇到这样的问题,所以就记录一下出现这种情况的几种情况。
问题分析
出现 Invalid bound statement (not found) 这个错误的原因:
是根据 mapper接口的全路径 以"."(点号)与方法名拼接成字符串,作为唯一key(下面将以key代替 ) 到 Map<String, MappedStatement> mappedStatements (后续已map 代替该对象)中去获取对应的MappedStatement, 如果获取不到就报这个错误。
根据上面的流程,也就解释了为什么mapper 中的方法不能重载的原因。因为获取MappedStatement 是根类和方法名有关,与参数无关。所以不能重载。
继续分析Invalid bound statement 这个错误,出现这个错误是因为获取不到MappedStatement,也就是说在map 容器中根据key 去获取值,没有获取到。
解决
那么问题来了,什么情况下在map中根据key 获取不到值呢?
其实获取不到就两种情况。
- 第一种情况: 就是map 是一个空集合。
- 第二种情况:map中没有这个key (也就是说key值不对)
什么情况下mappedStatements 这个map 为空呢?
回答这个问题要明白mybatis 的原理。
在项目启动的过程中,会扫描并解析扫描到的mapper.xml 文件,将xml文件的namespace 与select 、update 、insert、delete 标签的id 以 namespace.id 的形式组成一个唯一的key ,将sql语句封装成一个MappedStatement 对象作为value存储在mappedStatements 这个map 集合中。
所以当map集合为空,说明mapper.xml 没有被容器扫描到。
那什么情况下项目中有mapper.xml 文件却没有被扫描到呢?
回答这个问题,要清楚mybatis mapper.xml 文件的加载目录。
当我们没有在配置文件中配置指定目录或者配置配置错误的文件地址。
mybatis: mapper-locations: classpath:mybatis/mapper/*.xml
在容器启动的时候会到配置文件指定的目录和mapper 接口所在的包中查找,如果查找不到map集合就是空的。
这时候有的人该问
配置文件配置的mapper.xml 文件地址没有错误,为什么map 还是空的?
如果出现这个问题,我们需要排查一下target 目录中是否有mapper.xml 文件 因为maven 编译打包 会将代码编译打包成target文件中,程序运行也是读取加载该目录下的文件,而不是我们项目目录。
这时需要在pom 文件build中添加如下配置
<resources> <resource> <directory>src/main/java</directory> <includes> <include>**/*.xml</include> </includes> <filtering>false</filtering> </resource> <resource> <directory>src/main/resources</directory> <includes> <include>**/*.xml</include> <include>**/*.yml</include> </includes> <filtering>false</filtering> </resource> </resources>`
map为空总结
1、 检查mapper的xml文件 是否在mapper 接口包中。如果不在,说明指定了目录(目前一般都是在resource 资源目录下新建文件夹) 如果指定了目录 需要在配置文件中配置指定的目录。
注意:在resource 目录下创建多级目录时,要一层一层创建,不要像创建Java目录一下以"."隔开,这样是不对的。
2、项目配置没有问题,还出现这个问题,排查一下target 目录中是否有mapper.xml 。没有则说明maven 打包的时候没有将xml 文件打包进jar中,需要在pom中添加resource配置信息。
下面来说说第二种情况:key 值不正确
1、这种情况 需要排查mapper 接口全路径 与 mapper xml 文件中的namespace 配置是否一致。
这里有个验证技巧:
按住Ctrl 键 鼠标点击接口名 看看是否能正常跳转到接口中,如果能正常跳转,则说明映射成功,如果不能跳转,则说明namespace 配置的不正确,需要修改。
2、隐射成功,下一步拷贝接口中的方法名 到xml 文件中查找是否有对应的sql,排查xml sql 的id值是否与方法名一致。(注意空格)
这里也有一个排错技巧:
在idea 上安装 Free Mybatis plugin插件,这样 按住Ctrl 键 点击id 看是否能跳转到接口中对应的方法上。如果不能则说明id 的值不对,修改成方法名即可。
看到这里估计有人又该问了
我怎么知道map中是否为空呢?怎么知道key是不正确呢?
如果有看源码能力的,可以debug项目 追源码。
如果不想看源码的,我这里给一个很直接的方式。debug模式启动项目后,记住是在项目启动后,在mybatis 源码中打断点,然后请求 debug查看。
千万别在启动项目前打断点,因为项目启动加载也会走这里,这样会看迷糊的。记住是启动项目后,访问前 打断点
总结
这是我目前能找到错误的原因和解决的方式方法。
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
- 解决java中mybatis报错:org.apache.ibatis.binding.BindingException:Invalid bound statement(not found):xx问题
- mybatis整合springboot报BindingException:Invalid bound statement (not found)异常解决
- 使用mybatis报Invalid bound statement解决分析
- 解决微服务下Mybatis xml无效绑定问题及分析Invalid bound statement
- mybatis创建项目报Invalid bound statement (not found)错误解决方法
- SpringBoot使用MyBatis-Plus解决Invalid bound statement异常
- 解决mybatis-plus通用mapper调用报错:Invalid bound statement