解决多项目中,引入多个xml目录,导致找不到mapper对应的xml 报错:BindingException:Invalid bound statement (not found)

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();
}



猜你喜欢

转载自blog.csdn.net/HO1_K/article/details/129872009