`mapper-locations` 和 `@MapperScan`区别

mapper-locations@MapperScan 是 MyBatis/MyBatis-Plus 中分工完全不同 的两个配置:@MapperScan 管「Mapper接口的注册」,mapper-locations 管「XML文件的加载」,二者缺一不可,且无直接关联,以下是详细区别和协同关系:

一、核心区别(总览)

维度 @MapperScan mapper-locations
归属层面 Spring + MyBatis整合层(mybatis-spring) MyBatis核心层(mybatis/mybatis-plus)
作用对象 Java接口(Mapper接口,如MsWorkflowDao) XML文件(如MsWorkflowDao.xml)
配置形式 注解(加在启动类/配置类上) 配置项(yml/properties中)
核心目标 扫描Mapper接口,为其创建代理对象并注册到Spring容器,让@Autowired能注入 扫描XML文件,解析其中的SQL语句,绑定到Mapper接口的方法上
失败后果 注入Mapper接口时报NoSuchBeanDefinitionException 调用Mapper方法时报Invalid bound statement (not found)
多模块关键配置 扫描路径覆盖所有子模块的Mapper包(如com.example.**.dao classpath*:替代classpath:,扫描所有依赖jar中的XML

二、详细拆解

1. @MapperScan:管「Mapper接口的注册」(Spring层面)

你可以把它理解为:告诉Spring"去哪里找Mapper接口,并为这些接口创建可注入的代理对象"

  • 核心行为:
    扫描指定包下的所有Mapper接口(如com.example.**.dao下的MsWorkflowDao),通过MyBatis的MapperFactoryBean为每个接口创建MapperProxy代理对象,并将代理对象注册到Spring容器中。

  • 核心价值:
    没有它,你在Service中@Autowired MsWorkflowDao时,Spring会找不到这个Bean,直接报错;

  • 示例:

    java 复制代码
    // 扫描com.example下所有层级的dao包中的Mapper接口
    @MapperScan("com.example.**.dao")
    @SpringBootApplication
    public class MsApplication {}
2. mapper-locations:管「XML文件的加载」(MyBatis层面)

你可以把它理解为:告诉MyBatis"去哪里找XML文件,解析里面的SQL并绑定到Mapper接口方法上"

  • 核心行为:
    根据配置的路径扫描XML文件,解析XML中的<select>/<insert>等标签,将SQL语句与「namespace(Mapper接口全类名)+ id(接口方法名)」绑定,存入MyBatis的MapperRegistry中。

  • 核心价值:
    没有它,即使Mapper接口已被Spring注册,调用queryPage方法时,MyBatis也找不到对应的SQL,报「Invalid bound statement」;

  • 示例:

    yaml 复制代码
    mybatis-plus:
      # 多模块下用classpath*:扫描所有依赖jar中的XML
      mapper-locations: classpath*:com/example/**/dao/*.xml

三、二者的协同关系(缺一不可)

正常调用Mapper方法的流程是:

复制代码
Service中@Autowired注入Mapper接口 → Spring通过@MapperScan找到接口并返回代理对象 → 调用接口方法 → MyBatis通过mapper-locations加载的XML找到对应SQL → 执行数据库操作
  • 只有@MapperScan,没有mapper-locations
    Mapper接口能正常注入,但调用方法时MyBatis找不到SQL,报Invalid bound statement
  • 只有mapper-locations,没有@MapperScan
    XML被加载,但Mapper接口未被注册到Spring,注入时直接报NoSuchBeanDefinitionException
  • 两者都正确配置:
    Mapper接口被Spring注册为代理对象,XML中的SQL被MyBatis绑定到接口方法,调用正常。

四、常见误区(重点避坑)

  1. 误区1 :以为@MapperScan能扫描XML文件
    → 错!@MapperScan只扫描Java接口,完全不处理XML文件;
  2. 误区2 :以为mapper-locations能注册Mapper接口
    → 错!mapper-locations只加载XML,不会让Spring注册Mapper接口;
  3. 误区3 :多模块下,@MapperScan配了com.example.**.dao,但mapper-locations用了classpath:(少了*
    → 结果:Mapper接口能扫到,但子模块jar中的XML扫不到,仍报Invalid bound statement
  4. 误区4 :XML文件放在src/main/java下,只配了mapper-locations却没配置Maven资源扫描
    → 结果:XML未被打包到classpath,mapper-locations再正确也扫不到。

五、总结

配置 一句话总结 核心解决的问题
@MapperScan 让Spring能找到并注入Mapper接口 注入Mapper时的NoSuchBeanDefinition
mapper-locations 让MyBatis能找到Mapper接口对应的SQL(XML中) 调用方法时的Invalid bound statement

在多模块场景中,需同时保证:

  • @MapperScan的路径覆盖所有子模块的Mapper接口包;
  • mapper-locationsclasspath*:扫描所有子模块jar中的XML文件。
相关推荐
9523620 分钟前
MyBatis
后端·spring·mybatis
FQNmxDG4S2 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
虹科网络安全3 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje3 小时前
Java语法进阶
java·开发语言·jvm
rKWP8gKv74 小时前
Java微服务性能监控:Prometheus与Grafana集成方案
java·微服务·prometheus
老前端的功夫4 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_435287924 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
小江的记录本4 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
yaoxin5211234 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python
极客先躯6 小时前
高级java每日一道面试题-2025年11月24日-容器与虚拟化题[Dockerj]-runc 的作用是什么?
java·oci 的命令行工具·最小可用·无守护进程·完全标准·创建容器的核心流程·runc 核心职责思维导图