`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文件。
相关推荐
编程小Y2 小时前
Servlet 与 Tomcat 白话全解析:从核心原理到实战部署
java·servlet·tomcat
BD_Marathon2 小时前
【JavaWeb】Tomcat_简介
java·tomcat
⑩-2 小时前
Java-元注解 (Meta-Annotations)
java
Meteors.2 小时前
安卓进阶——原理机制
android·java·开发语言
是阿漂啊2 小时前
vscode运行springboot项目
java·spring boot·后端
ghfdgbg2 小时前
13. 配置优先级 + Bean的管理 + SpringBoot核心原理
java·spring boot·后端
Moe4882 小时前
Elasticsearch 8.1 Java API Client 客户端使用指南(索引、文档操作篇)
java·后端·面试
洋亦2 小时前
GoF23种设计模式 简介
java
Javatutouhouduan2 小时前
Java面试常问Redis核心知识点整理!
java·数据库·redis·java面试·后端开发·java架构师·java程序员