复杂查询组织:XML 结构规范与可读性
业务复杂后,一条 SQL 动辄几十行、动态条件满天飞,此时 Mapper XML 的"组织能力"决定可维护性。本节给出 XML 的结构规范:命名、复用、动态 SQL 的排版纪律。
骨架:namespace 与 statement
XML 的 namespace 必须是 Mapper 接口的全限定名,statement 的 id 与接口方法一一对应,MyBatis 靠这两项把 XML 与接口绑定(同一方法不能注解与 XML 双写,会冲突):
<mapper namespace="com.demo.mapper.UserMapper">
<resultMap id="UserMap" type="com.demo.entity.User">
<id column="id" property="id"/>
<result column="name" property="name"/>
</resultMap>
</mapper>
复用:sql 片段 + include
公共列清单、公共 WHERE 条件抽成 <sql>,需要处用 <include> 引用:
<sql id="userColumns">
id, name, email, status, create_time
</sql>
<select id="selectById" resultMap="UserMap">
SELECT <include refid="userColumns"/>
FROM user
WHERE id = #{id}
</select>
多条件查询把"非空才拼"的片段也抽出来,避免每个查询复制 if 判断;resultMap 之间可用 extends 继承父映射。
动态 SQL 排版纪律
<select id="pageSearch" resultType="User">
SELECT id, name, email
FROM user
<where>
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="status != null">
AND status = #{status}
</if>
</where>
ORDER BY id DESC
</select>
习惯性纪律:
- 用
<where>自动去掉多余的 AND/OR,别手拼WHERE 1=1; - 多分支取舍用
<choose>/<when>/<otherwise>,循环用<foreach>(collection 为 list/array 时参数名写list/array,或用 @Param 显式命名); <trim>处理前缀后缀;SQL 中出现<、>、&时包进<![CDATA[ ]]>,如WHERE age <![CDATA[ < ]]> 18;- 关键字大小写统一,每行一个条件;多表 JOIN 加别名,列引用写全
u.name; - 一个 XML 只服务一个实体/业务聚合,超长 SQL 拆方法或拆视图,别堆"千行 SQL"。
方法级规范
- 简单增删改用 @Insert/@Update 注解足够;带条件查询一律 XML——注解里拼动态 SQL 可读性差还易出引号错误;
- 参数多时用
@Param("xxx")命名或传对象,XML 里写#{xxx},别靠位置猜参数; - 列名规范(或开启驼峰映射)后,简单查询用 resultType 即可,复杂映射才写 resultMap。
XML 结构规范的核心是少重复、可拼接、易审阅:sql 片段抽列、where 收敛条件、resultMap 管映射、一文件一主题。SQL 是团队最贵的资产之一,排版即沟通。