Resolving MyBatis-Plus XML Mapper Scanning Issues in Spring Boot with Gradle

Project Setup with MyBatis-Plus and Gradle

Start with a standard Spring Boot 2.3.x project using Gradle. Below is a minimal build.gradle configuration:

plugins {
    id 'org.springframework.boot' version '2.3.12.RELEASE'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'mysql:mysql-connector-java:8.0.33'
    implementation 'com.baomidou:mybatis-plus-boot-starter:3.5.7'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation('org.springframework.boot:spring-boot-starter-test') {
        exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

Configure data base and MyBatis-Plus in application.yml:

server:
  port: 8090

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/test_demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: 123456

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  # Explicitly declare mapper XML locations if non-default
  mapper-locations: classpath:/mappers/**/*.xml

Define a mapper interface:

package com.example.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.entity.Item;

public interface ItemMapper extends BaseMapper<Item> {
    Item fetchById(Long itemId);
}

Corresponding XML file at src/main/resources/mappers/ItemMapper.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.mapper.ItemMapper">
    <select id="fetchById" resultType="com.example.entity.Item">
        SELECT * FROM t_item WHERE id = #{itemId}
    </select>
</mapper>

Enable scanning via configuration class:

@Configuration
@MapperScan("com.example.mapper")
@EnableTransactionManagement
public class PersistenceConfig {}

Common XML Scanning Pitfalls and Fixes

1. Incorrect Resource Directory Name

If you rename src/main/resources/mappers to src/main/resources/xmls, the default classpath*:/mapper/**/*xml pattern no longer matches. To resolve this, explicitly configure mapper-locations in application.yml:

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

2. Storing XML Files Under src/main/java

Placing XML files in side Java source directories (e.g., src/main/java/com/example/mapper/ItemMapper.xml) causes them to be excluded from the build output by default — Gradle does not copy non-Java resources from src/main/java unless instructed.

To include these files, extend the resource processing step in build.gradle:

processResources {
    from('src/main/java') {
        include '**/*.xml'
        include '**/*.properties'
    }
}

Alternatively, configure sourceSets more precisely:

sourceSets.main.resources {
    srcDirs = ['src/main/resources', 'src/main/java']
    excludes = ['**/*.java']
}

After applying either change, rebuild the project. Verify that generated JAR/WAR contains XML files under com/example/mapper/.

3. Verifying Classpath Resolution

At runtime, MyBatis-Plus uses ResourcePatternResolver to locate XML files. The default pattern is classpath*:/mapper/**/*xml. You can confirm resolution behavior by enabling debug logging:

logging:
  level:
    org.springframework.core.io.support.PathMatchingResourcePatternResolver: DEBUG

This reveals which paths are scanned and which resources are matched.

Best Pratcices

  • Prefer placing XML mappers under src/main/resources with conventional naming (/mappers/) to avoid custom configuration.
  • Avoid mixing XML and Java sources in the same package unless necessary — it complicates builds and IDE indexing.
  • Always validate that XML files appear in the final artifact’s classpath before troubleshooting binding errors.
  • Use @Select annotations for simple queries to bypass XML entirely when appropriate.

Tags: spring-boot mybatis-plus Gradle xml-mapping build-configuration

Posted on Wed, 29 Jul 2026 16:25:04 +0000 by suge