XML写接口适用场景举例

XML 写接口主要解决的是 Wrapper 搞不定的复杂场景,核心适用场景可以归纳为以下五类:

一、多表 JOIN 关联查询

一旦涉及多表关联,字段来源复杂,用 Wrapper 拼 JOIN 或子查询会极其难读且难调试,此时应回归 XML。

java 复制代码
// Mapper 接口
List<UserDeptVO> selectUserWithDept(@Param("status") Integer status);
xml 复制代码
<!-- XML -->
<select id="selectUserWithDept" resultType="com.example.vo.UserDeptVO">
    SELECT u.id, u.name, d.dept_name AS deptName
    FROM user u
    LEFT JOIN department d ON u.dept_id = d.id
    WHERE u.status = #{status}
</select>

二、复杂统计与报表查询

当查询目的不是获取原始数据,而是返回聚合结果(GROUP BY、计算字段、返回 VO 对象)时,本质是数据加工,用 XML 配合 ResultMap 更清晰。

xml 复制代码
<select id="selectDeptStats" resultType="com.example.vo.DeptStatsVO">
    SELECT d.dept_name,
           COUNT(u.id) AS userCount,
           AVG(u.age) AS avgAge
    FROM department d
    LEFT JOIN user u ON d.id = u.dept_id
    GROUP BY d.dept_name
    HAVING COUNT(u.id) > 5
</select>

三、需要深度 SQL 优化与索引控制

当你需要关心查询是否走索引、JOIN 顺序是否正确、执行计划是否合理时,手写 SQL 是必要的------可控性比省代码更重要。

xml 复制代码
<!-- 明确指定索引、控制 JOIN 顺序 -->
<select id="selectOptimized" resultType="com.example.entity.Order">
    SELECT /*+ INDEX(o idx_order_user_id) */ o.*
    FROM `order` o FORCE INDEX (idx_create_time)
    INNER JOIN user u ON o.user_id = u.id
    WHERE o.create_time > #{startTime}
      AND u.status = 1
    ORDER BY o.create_time DESC
    LIMIT 1000
</select>

四、大批量数据操作

对于海量数据的批量插入或更新,虽然 MP 提供了 saveBatch,但在极端性能要求下,手写基于 <foreach> 的批量 SQL 性能更好。

xml 复制代码
<!-- 批量插入 -->
<insert id="insertBatch">
    INSERT INTO user (uuid, username, age)
    VALUES
    <foreach collection="list" item="u" separator=",">
        (#{u.uuid}, #{u.username}, #{u.age})
    </foreach>
</insert>

<!-- 批量删除(IN 语句) -->
<delete id="deleteBatchIds">
    DELETE FROM user
    WHERE id IN
    <foreach collection="idList" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</delete>

五、复杂动态条件拼接

虽然 Wrapper 的 condition 参数能处理大部分动态条件,但遇到**多条件分支(类似 switch-case)**的场景,XML 的 <choose>/<when> 标签更直观。

xml 复制代码
<select id="selectUser" resultType="com.example.entity.User">
    SELECT * FROM user
    <where>
        <choose>
            <when test="id != null">
                AND id = #{id}
            </when>
            <when test="name != null">
                AND name = #{name}
            </when>
            <when test="age != null">
                AND age = #{age}
            </when>
            <otherwise>
                1 = 1
            </otherwise>
        </choose>
    </where>
</select>

判断标准

一个非常实用的工程化判断标准是:如果这个 SQL,你愿意直接在数据库客户端里单独执行、调试、优化,那就手写 XML;如果这个 SQL 只是单表 CRUD 的一种表达,那就用 Mapper 自带的方法 + Wrapper。

在健康的项目架构中,通常遵循 "70% 通用 CRUD + 30% 自定义 SQL" 的混合模式。


需要我帮你整理一份 MyBatis-Plus 的分页插件配置和使用示例吗?

相关推荐
m0_58738300几秒前
深圳 24 小时自助健身房系统软件开发实战指南与案例解析
java·spring boot·小程序·架构·需求分析
Nebula_g11 分钟前
JavaSE项目实践:红包雨-线程池/线程
java·开发语言
小羊没烦恼!12 分钟前
jQuery1.5的改进细节
java·服务器·开发语言·前端·c#
霸道流氓气质14 分钟前
Prompt 版本控制与 A/B 测试实战:语义版本管理、一致性哈希分流与 Thompson Sampling 的 Java 生产级实现
java·prompt·哈希算法
独孤九剑打醒他20 分钟前
【原创开源·修订版】源-栅-漏-栅-源横向双栅MOS:从“被误解的短路”到“电流路径多值逻辑与顶层供电架构”
前端·嵌入式硬件·架构·开源·硬件工程
阿狗童鞋34 分钟前
React实战指南
前端·react.js·前端框架
v:ychya20181 小时前
独立站外贸建站公司怎么选?建站就要建营销型网站
前端·php
嵌入式er1 小时前
影石系统组 一二面OC面经
java·开发语言
春涧草茶1 小时前
慢就是快12-12手动抛出异常
java·linux·前端
三小河1 小时前
从 Markdown 到 Generative UI:AI 如何从“生成答案”进化到“生成界面”?
前端·人工智能·后端