解决多项目中的报错:BindingException:Invalid bound statement (not found)

在SpringBoot项目中,当引入多个XML目录后,MybatisPlus的Mapper方法报错找不到。问题出在MybatisPlusConfig配置类中,资源扫描未处理多资源情况。解决方案是手动加载多个XML资源,通过PathMatchingResourcePatternResolver分别获取不同路径的资源并合并设置到SqlSessionFactoryBean。

1. 情况描述

分析过程可以直接跳过,直接看解决方法

在只引入了一个xml目录时,程序运行正常,各个Mapper方法也可以正常调用,后续其它开发同志引入了其他包中的xml目录,导致调用Mapper的所有方法都报错,最后没找到原因也没解决,然后交给了我解决。

版本信息:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.5.1</version>
	<relativePath/>
</parent>

<dependency>
	<groupId>com.baomidou</groupId>
	<artifactId>mybatis-plus-boot-starter</artifactId>
	<version>3.5.1</version>
</dependency>

yml中原mybatis配置:

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

引入其它包后的配置:

mybatis:
  mapper-locations: classpath*:/mapper/**/*.xml, classpath*:/xmls/**/*.xml

mybatis-plus配置类:

@Configuration
public class MybatisPlusConfig {

    @Value("${mybatis-plus.mapper-locations}")
    private String mapperLocations;

    @Bean
    public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
            throws Exception {
        final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource);
        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
        // 设置公共字段的拦截
        GlobalConfig globalConfig = GlobalConfigUtils.defaults();
        sessionFactory.setGlobalConfig(globalConfig);
        return sessionFactory.getObject();
    }
}



2. 报错信息
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): cn.mmd.orm.mapper.health.HealthRecordsMapper.selectRecords
	at org.apache.ibatis.binding.MapperMethod$SqlCommand.<init>(MapperMethod.java:235) ~[mybatis-3.5.10.jar:3.5.10]
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.<init>(MybatisMapperMethod.java:50) ~[mybatis-plus-core-3.5.2.jar:3.5.2]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.lambda$cachedInvoker$0(MybatisMapperProxy.java:111) ~[mybatis-plus-core-3.5.2.jar:3.5.2]
	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[?:1.8.0_171]
	at com.baomidou.mybatisplus.core.toolkit.CollectionUtils.computeIfAbsent(CollectionUtils.java:115) ~[mybatis-plus-core-3.5.2.jar:3.5.2]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.cachedInvoker(MybatisMapperProxy.java:98) ~[mybatis-plus-core-3.5.2.jar:3.5.2]
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.5.2.jar:3.5.2]
	at com.sun.proxy.$Proxy136.selectRecordByIdCardNumber(Unknown Source) ~[?:?]
	……
  1. 看到这个报错的时候,我第一时间怀疑是不是yml中的classpath地址写错了,检查发现没得问题。之前可以运行成功就证明Mapper.xml中的namespace写错或者方法名写错等问题是不存在的,这里不考虑。
mybatis:
  mapper-locations: classpath*:/mapper/**/*.xml, classpath*:/xmls/**/*.xml
  1. 然后有怀疑是新加的classpath没有扫描成功,检查pom配置后发现是有扫描所有xml文件的:
<resources>
	<resource>
		<directory>src/main/resources</directory>
		<includes>
			<include>**/*.yml</include>
			<include>**/*.xml</include>
			<include>**/*.properties</include>
		</includes>
		<filtering>true</filtering>
	</resource>
</resources>
  1. 随后查看jar包中也有mapper和xmls对应的jar包和他们的xml文件。

    到这里其实就很疑惑,之前从来没碰到过这种问题,网上搜索一番后也没什么新发现。

  2. 没法只能打断点看看哪里出了问题,最后发现是MybatisPlusConfig配置类扫描资源的问题:
    在这里插入图片描述

new PathMatchingResourcePatternResolver().getResources(mapperLocations)这个类扫描xml资源的时候,一条资源也没返回。这下找到原因了,最后点进源码查看,才发现这一个版本资源扫描根本就没有处理多资源的情况!!!!
在这里插入图片描述

根目录只识别了mapper这个文件夹,文件的匹配模式直接就截取了根目录后面的所有内容:

**/*.xml,classpath*:/xmls/**/*.xml

在这里插入图片描述

这下找到原因就好办了,进入解决问题模式。



3. 解决方法

手动加载多个xml资源

@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSource)
        throws Exception {
    final MybatisSqlSessionFactoryBean sessionFactory = new MybatisSqlSessionFactoryBean();
    sessionFactory.setDataSource(dataSource);
    // 多mapper地址手动加载
    PathMatchingResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
    String[] split = mapperLocations.split(",");
    Resource[] resources = resourcePatternResolver.getResources(split[0]);
    Resource[] resources1 = resourcePatternResolver.getResources(split[1]);
    // 合并两个mapper资源
    sessionFactory.setMapperLocations(ArrayUtil.addAll(resources, resources1));
    // 设置公共字段的拦截
    GlobalConfig globalConfig = GlobalConfigUtils.defaults();
    sessionFactory.setGlobalConfig(globalConfig);
    return sessionFactory.getObject();
}



### Spring Boot 3.2.5 使用 Gradle 构建时解决 MyBatis BindingException 错误 MyBatis 的 `BindingException` 错误通常表示在运行时无法找到绑定的 SQL 语句。这可能是由于 Mapper 接口与对应的 XML 文件未正确映射,或者配置文件中某些路径设置不正确导致的。 #### 1. 检查依赖配置 确保在 `build.gradle` 中正确添加了 MyBatis-Plus 和相关依赖项。以下是推荐的依赖配置: ```gradle dependencies { implementation 'com.baomidou:mybatis-plus-spring-boot3-starter:3.5.5' implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3' } ``` 上述依赖项分别引入了 MyBatis-Plus 和 MyBatis-Spring 支持[^2]。 #### 2. 配置 `application.yml` 确保 `application.yml` 中的 `mybatis-plus` 配置正确,特别是 `mapper-locations` 和 `type-aliases-package` 的路径设置。以下是一个示例配置: ```yaml mybatis-plus: mapper-locations: classpath*:/mapper/*Mapper.xml type-aliases-package: com.example.arrow_smart_toilet_back_01.mapper configuration: map-underscore-to-camel-case: true log-impl: org.apache.ibatis.logging.stdout.StdOutImpl global-config: db-config: id-type: auto ``` 如果项目使用的是自定义包名,请根据实际情况调整 `mapper-locations` 和 `type-aliases-package` 的值[^2]。 #### 3. 确保 Mapper 接口和 XML 文件匹配 `BindingException` 常见原因之一是 Mapper 接口与对应的 XML 文件未正确关联。请检查以下几点: - Mapper 接口是否被标注为 `@Mapper` 或通过 `@MapperScan` 注解注册。 - XML 文件是否放置在正确的目录下(例如 `src/main/resources/mapper/`)。 - XML 文件中的 `namespace` 属性是否与 Mapper 接口的全限定名一致。 例如,假设有一个名为 `UserMapper` 的接口,其 XML 文件应如下配置: ```xml <mapper namespace="com.example.arrow_smart_toilet_back_01.mapper.UserMapper"> <!-- SQL statements --> </mapper> ``` #### 4. 删除冗余配置类 如果项目中存在手动编写的 Druid 数据源配置类(如 `MysqlDruidConfiguration.java` 和 `DruidDataSourceProperties.java`),建议删除这些类。Spring Boot 已经内置了对 Druid 的支持,手动配置可能会导致冲突[^3]。 #### 5. 实现分页功能 如果需要实现分页功能,可以引入 `PageHelper` 相关依赖。以下是 Gradle 配置示例: ```gradle dependencies { implementation 'com.github.pagehelper:pagehelper-spring-boot-starter:2.1.0' } ``` 同时,确保在服务层代码中正确调用分页方法。例如: ```java import com.baomidou.mybatisplus.extension.plugins.pagination.Page; public List<User> getUserList(int page, int size) { Page<User> userPage = new Page<>(page, size); return userMapper.selectPage(userPage, null).getRecords(); } ``` #### 6. 调试与验证 如果问题仍然存在,可以通过以下方式排查: - 启用 MyBatis 日志输出,检查 SQL 执行情况。 - 确保项目构建后,XML 文件已正确打包到 `resources` 目录下。 --- ### 示例代码 以下是一个完整的 Mapper 接口和 XML 文件示例: #### Mapper 接口 ```java package com.example.arrow_smart_toilet_back_01.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.example.arrow_smart_toilet_back_01.entity.User; import org.apache.ibatis.annotations.Mapper; @Mapper public interface UserMapper extends BaseMapper<User> { } ``` #### XML 文件 ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.arrow_smart_toilet_back_01.mapper.UserMapper"> <select id="selectById" resultType="com.example.arrow_smart_toilet_back_01.entity.User"> SELECT * FROM user WHERE id = #{id} </select> </mapper> ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值