Mybatis xml 无法正常解析org.apache.ibatis.binding.BindingException_ Invalid bound statement

问题背景

使用插件 mybatisX 生成的 mapper.xml 没有办法被正常解析,项目使用的是 nacos 作为配置中心;

问题定位

1. 首先看了一下网上说的常见几种问题,比如 id 不匹配,或者说 pom 里缺少 resource 配置导致 target 里没有 xml;这些都没有出现; 2. 那接下来就只能从源码出发解决问题; 3. 通过报错的堆栈信息我发现问题的出发点是在这里
    public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
      final String methodName = method.getName();
      final Class<?> declaringClass = method.getDeclaringClass();
      MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
          configuration);
      if (ms == null) {
        if (method.getAnnotation(Flush.class) != null) {
          name = null;
          type = SqlCommandType.FLUSH;
        } else {
          throw new BindingException("Invalid bound statement (not found): "
              + mapperInterface.getName() + "." + methodName);
        }
      } else {
        name = ms.getId();
        type = ms.getSqlCommandType();
        if (type == SqlCommandType.UNKNOWN) {
          throw new BindingException("Unknown execution method for: " + name);
        }
      }
    }

ms == null 这个判断返回了 true,因此我们继续看 resolveMappedStatement 这个方法为什么会出现 null;

    private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
        Class<?> declaringClass, Configuration configuration) {
      String statementId = mapperInterface.getName() + "." + methodName;
      if (configuration.hasStatement(statementId)) {
        return configuration.getMappedStatement(statementId);
      } else if (mapperInterface.equals(declaringClass)) {
        return null;
      }
      for (Class<?> superInterface : mapperInterface.getInterfaces()) {
        if (declaringClass.isAssignableFrom(superInterface)) {
          MappedStatement ms = resolveMappedStatement(superInterface, methodName,
              declaringClass, configuration);
          if (ms != null) {
            return ms;
          }
        }
      }
      return null;
    }

这里面是 configuration 中的mappedStatements中我想要的 sql 方法不存在;这时候我就怀疑我的 xml 解析因为没有正确被解析器解析导致了问题的出现;

接下来看这个类MybatisPlusAutoConfiguration.java,这个类里的这个构造方法提供了 xml 的解析能力;

@Bean
@ConditionalOnMissingBean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
// 中间省略不必要的行
Resource[] mapperLocations = this.properties.resolveMapperLocations();
if (!ObjectUtils.isEmpty(mapperLocations)) {
    factory.setMapperLocations(mapperLocations);
}

我打上断点,重启项目;结果发现根本没有走到断点这里;也就是说 xml 解析能力根本没有派上用场;

接下来问题的关键就昭然若揭了;因为这个类有@Bean ,如果没有初始化说明有其他的 bean 覆盖了这个代码块的初始化逻辑;在项目里全局搜索SqlSeesionFactory,果然找到一块定义 bean 的代码;

最后解决方式就是在这个自定义 bean 的方法里面,补上 MapperLocations 的赋值逻辑;

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
        MybatisSqlSessionFactoryBean factory = new MybatisSqlSessionFactoryBean();
        factory.setDataSource(dataSource);
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        factory.setMapperLocations(resolver.getResources(mapperLocations));
        return factory.getObject();
    }

最后总结

多看源码、多打断点调试;像这个问题最开始按网上列举的常见5 种错误原因试,花费了很多时间成本,但都无助于解决问题;后面一步一步断点调试,从源码入手才顺利分析成功问题;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值