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 的分页插件配置和使用示例吗?

相关推荐
IMPYLH1 小时前
HTML 的 <slot> 元素
前端·网络·html
今天的接口写完了吗?1 小时前
Java 使用 OkHttp 调用外部接口
java
计算机魔术师1 小时前
AI行业周末炸锅:有人要踩刹车,有人嫌你刹车片太厚
前端
yuzhiboyouye1 小时前
零sql和xml写接口,的区别是什么,过程是什么,举例一下下,用mybatis-plus+ spring-boot
java·服务器·前端
怕浪猫1 小时前
构建你自己的 AI Agent 发行版:从 Profile 定制到生产部署全流程
前端·后端·面试
小王师傅662 小时前
【设计模式】装饰模式(四):框架源码实战——从 Java I/O 到 Spring 到 MyBatis
java·设计模式
深圳市益普科技有限公司2 小时前
半导体CIM数据底座:四步把多厂数据拉通
前端
nvvas2 小时前
Spring AI 2.0正式GA:Token砍掉64%,Java的AI反击战打响了
java·人工智能
程序员阿鹏2 小时前
双亲委派机制
java·jvm·数据结构·后端