美文网首页
Mybatis Invalid bound statement

Mybatis Invalid bound statement

作者: MinXie | 来源:发表于2022-04-10 22:54 被阅读0次

前两天在项目中遇到个很神奇的问题,想着周末有空的时候给解一下

问题的现象

在IDEA中执行main方法能正常跑通程序</br>
但是打包后,执行jar包会报错,错误信息如下:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

是在调用Mapper方法的时候抛出的异常


image.png

大胆猜测,小心求证

此时心中隐隐有答案,猜测大概率是数据源有问题,为了求证心中所想

我在报错的地方打了个断点,在两种不同的场景下分别进行调试

main调试

查看Mapper对应的数据源信息


image.png

jar包调试

使用调试模式执行jar包,打开命令行执行下面命令

java -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=y  -jar main.jar

在IDEA中配置端口号

  • 添加新的配置 选择Remote JVM Debug
  • 填写Host: localhost Port: 5000
  • -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5000
image.png image.png
经过对比发现,Mapper注入的数据源果真是不一样的!

为什么会不一样呢???

代码都是一样的,配置也一样的,为啥打完jar后执行 注入的数据源就不同!

这时会怀疑是不是打包有问题,然后又解压了jar包去看,发现Mapper文件,数据源配置也都在,那大概可以排除是打包的问题了。

这条路走不通,那就换个思路去查一波

现在是可以定位到Mapper注入的数据源是异常的,那就查一下Mapper在注入这个数据源的时候发生了啥

那么Mapper是什么时候被Spring扫描的呢?

看一下spring-mybatis.xml配置文件发现配置了一个bean MapperScannerConfigurer

这个bean注入了扫描的mapper包位置和注入的数据源信息

image.png image.png

MapperScannerConfigurer类说明会从basePackage包开始递归实例化Mapper接口

好,那就先断个点在注入Mapper包(basePackage)的地方,debug看看,

image.png

观察一下前面执行的栈


image.png
  • PostProcessorRegistrationDelegate中调用了invokeBeanFactoryPostProcessors
    方法
  • 该方法会获取BeanDefinitionRegistryPostProcessor类型的需要实例化的beanName列表
  • MapperScannerConfigurer刚好继承BeanDefinitionRegistryPostProcessor
  • 接着调用beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)去实例化该bean

好了,到了这,真相快大白了,前面的时候我们已经知道Mapper是注入了别的数据源,而项目中的数据源也比较多,那就有可能是别的配置文件里也扫描了该Mapper

然后谁先搜索到该Mapper就会注入该类型的数据源

果不其然,翻了别的配置文件一看,有个basePackage使用了通配符匹配,把该Mapper也扫描了进去!!!


image.png

为了验证是不是这个原因,我把该basePackage改了一下,不要扫描到该Mapper,打包执行,程序跑通了!没想到没想到。

再深入挖一下

问题出现的前提条件

  • 项目中有多个spring-xxx.xml配置文件
  • 打成jar包,使用java -jar执行

那接着来看看spring扫描配置文件在不同场景下的做法

通过debug后定位到方法org.springframework.core.io.support.PathMatchingResourcePatternResolver#findPathMatchingResources

该方法会返回一个Resource数组,表示扫描的配置文件顺序

image.png
  • doFindPathMatchingJarResources: 查找Jar文件里的配置文件

很正常的通过迭代器获取文件

image.png
  • doFindPathMatchingFileResources: 查找文件系统内的配置文件

这里的方法调用链会比较深,最后定位到方法
org.springframework.core.io.support.PathMatchingResourcePatternResolver#doRetrieveMatchingFiles
需要注意的是这里调用了Arrays.sort对文件进行了排序

image.png
image.png

所以才会有这么戏剧性的bug出现

相关文章

网友评论

      本文标题:Mybatis Invalid bound statement

      本文链接:https://www.haomeiwen.com/subject/mtvbsrtx.html