Solve the problem of introducing multiple xml directories in a multi-project, resulting in the error that the xml corresponding to the mapper cannot be found: BindingException: Invalid bound statement (not found)

1. Situation description

The analysis process can be skipped directly and directly look at the solution

When only one xml directory is introduced, the program runs normally, and each Mapper method can be called normally. Later, other development comrades introduced xml directories in other packages, causing all methods of calling Mapper to report errors. Finally, the reason was not found and the solution was not resolved. , and handed it over to me to solve.

Version Information:

<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 Zhongyuan mybatis configuration:

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

Configuration after introducing other packages:

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

mybatis-plus configuration class:

@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. Error message

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. When I saw this error report, I immediately wondered if the classpath address in yml was wrongly written, and I found no problem after checking. It can be successfully run before, which proves that there are no problems such as wrongly written namespace or wrongly written method name in Mapper.xml, which will not be considered here.
mybatis:
  mapper-locations: classpath*:/mapper/**/*.xml, classpath*:/xmls/**/*.xml
  1. Then there is a suspicion that the newly added classpath has not been scanned successfully. After checking the pom configuration, it is found that all xml files are scanned:
<resources>
	<resource>
		<directory>src/main/resources</directory>
		<includes>
			<include>**/*.yml</include>
			<include>**/*.xml</include>
			<include>**/*.properties</include>
		</includes>
		<filtering>true</filtering>
	</resource>
</resources>
  1. Then check that there are also jar packages corresponding to mapper and xmls and their xml files in the jar package.

    I am actually very confused here, I have never encountered this kind of problem before, and I found nothing new after searching the Internet.

  2. There is no way but to interrupt the point to see what went wrong, and finally found that it is a problem with the MybatisPlusConfig configuration class scanning resources:
    insert image description here

When the new PathMatchingResourcePatternResolver().getResources(mapperLocations) class scans xml resources, no resource is returned. Now I found the reason, and finally clicked into the source code to view, only to find that the resource scan of this version did not handle multiple resources at all! ! ! !
insert image description here

The root directory only recognizes the mapper folder, and the matching mode of the file directly intercepts all the content behind the root directory:

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

insert image description here

Now it's easy to find the reason and enter the problem-solving mode.



3. Solutions

Manually load multiple xml resources

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



Guess you like

Origin blog.csdn.net/HO1_K/article/details/129872009