在 MyBatis Plus 中,mapper.xml 是核心的 SQL 映射配置文件,用于编写自定义 SQL 语句,实现复杂的数据库增、删、改、查操作。相比 MyBatis Plus 提供的通用 CRUD 方法,XML 文件支持动态 SQL、多表关联、复杂查询等场景,能完美适配多样化的业务逻辑。
MyBatis Plus 整合 XML 映射文件的核心是配置扫描路径,确保框架能加载到自定义的 XML 文件,完成接口与 SQL 的绑定。
在 application.yml 中配置 Mapper XML 的扫描路径,这是框架加载 XML 的核心配置:
mybatis-plus:
# 配置 Mapper XML 文件的扫描路径
mapper-locations: classpath*:/mapper/**/*.xml
# 【补全】配置实体类别名包,简化 XML 中 resultType 写法
type-aliases-package: com.lusifer.boot.domain配置说明
mapper-locations:指定 XML 文件的存放位置,classpath* 表示扫描所有模块(多模块 Maven 项目必须加),/mapper/**/*.xml 匹配 mapper 目录下所有子目录的 XML 文件;
type-aliases-package:为实体类配置别名,后续 XML 中可直接使用类名,无需书写全限定类名。
在项目的 src/main/resources/mapper 目录下,创建与 Mapper 接口同名的 XML 文件(示例:UserMapper.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 接口的全限定类名 -->
<mapper namespace="com.lusifer.boot.mapper.UserMapper">
<!-- 自定义查询语句:根据 ID 查询用户 -->
<select id="findById" resultType="User">
SELECT * FROM user WHERE id = #{id}
</select>
</mapper>标签说明
DOCTYPE:声明 XML 约束,必须保留,否则框架无法识别标签;
<mapper>:根标签,namespace 是唯一绑定标识,必须与 Mapper 接口全类名一致;
<select>:查询标签,对应 SELECT 语句,新增 / 修改 / 删除分别对应 <insert>/<update>/<delete>。
创建 Mapper 接口,继承 MyBatis Plus 的 BaseMapper,并声明与 XML 中 id 一致的方法:
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.lusifer.boot.domain.User;
@Mapper
public interface UserMapper extends BaseMapper<User> {
/**
* 根据 ID 查询用户(与 XML 中 id="findById" 对应)
* @param id 用户 ID
* @return 用户实体
*/
User findById(@Param("id") Long id);
}@Mapper:让 Spring 扫描并创建 Mapper 接口的代理对象;也可在启动类添加 @MapperScan("com.lusifer.boot.mapper") 统一扫描;
@Param("id"):指定参数名称,与 XML 中 #{id} 对应,多参数场景必须添加。
编写测试用例,调用自定义的 XML 方法,验证功能是否正常:
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testFindById() {
// 调用 XML 中定义的自定义方法
User user = userMapper.findById(1L);
System.out.println("查询结果:" + user);
}
}Mapper XML 是 MyBatis 的核心配置文件,负责Java 对象与数据库数据的映射,包含参数映射、结果映射两大核心功能。
命名规则:XML 文件名与对应 Mapper 接口完全一致(如 UserMapper.java 对应 UserMapper.xml);
存放规范:推荐放在 resources/mapper 目录下,与 Mapper 接口的包结构形成对应,便于维护。
参数映射用于将 Java 方法的参数传递到 SQL 语句中,MyBatis 提供 #{} 和 ${} 两种占位符,用法与安全性差异极大。
替换机制:SQL 预编译阶段替换为 ? 占位符,自动处理参数转义、类型转换;
核心优势:防止 SQL 注入,是业务开发的首选;
适用场景:所有普通参数(数值、字符串、日期等)。
<select id="findByName" resultType="User">
SELECT * FROM user WHERE username = #{username}
</select>替换机制:SQL 执行前直接字符串拼接,无预编译处理;
核心风险:存在 SQL 注入漏洞;
适用场景:仅用于动态传入表名、列名、排序字段等非数据参数。
<select id="findByColumn" resultType="User">
SELECT * FROM user WHERE ${columnName} = #{columnValue}
</select>将数据库查询结果映射为 Java 实体对象,支持 resultType 和 resultMap 两种方式。
简单映射
直接指定返回的实体类型(配合别名配置,可直接写类名),适用于字段名完全匹配的场景:
<select id="findAll" resultType="User">
SELECT * FROM user
</select>自定义映射
适用于字段名不匹配、多表关联查询、嵌套对象等复杂场景,手动配置列与属性的映射关系:
<!-- 定义结果映射规则 -->
<resultMap id="userResultMap" type="User">
<!-- 主键映射 -->
<id column="id" property="id"/>
<!-- 普通字段映射:column=数据库列名,property=实体属性名 -->
<result column="user_name" property="username"/>
<result column="create_time" property="createTime"/>
</resultMap>
<!-- 使用自定义 resultMap -->
<select id="findById" resultMap="userResultMap">
SELECT id, user_name, create_time FROM user WHERE id = #{id}
</select>动态 SQL 是 MyBatis 的核心特性,通过标签拼接 SQL 语句,实现根据参数动态生成条件,无需手动拼接字符串。
基础条件判断,满足条件则拼接对应的 SQL 片段:
<select id="findUserByCondition" resultType="User">
SELECT * FROM user
<where>
<if test="id != null">AND id = #{id}</if>
<if test="username != null and username != ''">AND username = #{username}</if>
<if test="age != null">AND age = #{age}</if>
</where>
</select>标签说明
<where>:自动去除开头多余的 AND/OR,避免 SQL 语法错误。
等效于 Java 的 switch-case,多选一执行条件:
<select id="findUserByChoose" resultType="User">
SELECT * FROM user
<where>
<choose>
<when test="username != null">AND username = #{username}</when>
<when test="email != null">AND email = #{email}</when>
<!-- 所有条件都不满足时执行 -->
<otherwise>AND status = 1</otherwise>
</choose>
</where>
</select>专用于 UPDATE 语句,自动去除结尾多余的逗号,避免语法错误:
<update id="updateUser">
UPDATE user
<set>
<if test="username != null">username = #{username},</if>
<if test="age != null">age = #{age},</if>
</set>
WHERE id = #{id}
</update>用于批量操作(批量查询、批量插入、批量删除),遍历集合 / 数组:
<!-- 批量根据 ID 查询用户 -->
<select id="findByIds" resultType="User">
SELECT * FROM user WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>属性说明
collection:遍历的集合 / 数组名称;
item:遍历的每一个元素;
open/close:拼接的开头 / 结尾字符;
separator:元素之间的分隔符。
XML 语法中,<、>、& 等字符属于保留字符,直接写在 SQL 中会报错,需通过两种方式处理。
使用 XML 预定义的转义字符替换特殊符号:
示例:
<select id="findByAge" resultType="User">
SELECT * FROM user WHERE age > #{minAge} AND age < #{maxAge}
</select>将 SQL 语句放在 <![CDATA[ ]]> 块中,忽略所有特殊字符解析,适合复杂条件:
<select id="findByAge" resultType="User">
<![CDATA[
SELECT * FROM user WHERE age > #{minAge} AND age < #{maxAge}
]]>
</select>CDATA 块内不支持动态 SQL 标签(如 <if>、<where>),仅用于纯 SQL 片段。
XML 文件找不到 原因:mapper-locations 配置错误,或 XML 文件未放在 resources/mapper 目录; 解决方案:检查路径配置,确保 classpath*:/mapper/**/*.xml 匹配文件位置。
方法绑定失败 原因:XML 中 id 与接口方法名不一致,或 namespace 与接口全类名不匹配; 解决方案:严格保证名称一致。
参数无效 原因:未加 @Param 注解,或 XML 中占位符名称与参数名不一致; 解决方案:多参数场景必须添加 @Param 注解。
SQL 注入风险 原因:滥用 ${} 占位符; 解决方案:业务参数统一使用 #{} 。
整合 MyBatis Plus 与 XML 的核心是配置 mapper-locations,多模块项目必须使用 classpath*;
参数映射优先用 #{} 保证安全,${} 仅用于动态表名 / 列名;
结果映射简单场景用 resultType,复杂场景用 resultMap;
动态 SQL 常用 <if>、<where>、<set>、<foreach> 标签,灵活拼接条件;
XML 特殊字符优先用转义字符,复杂 SQL 可使用 CDATA 块。