mapper.xml中的大于等于、小于等于

你关注的是 MyBatis 的 mapper.xml 中如何正确处理「大于等于(>=)」和「小于等于(<=)」,以及相关的使用技巧(包括固定写法和动态优化),下面详细拆解:

一、核心问题:为什么不能直接在 mapper.xml 中写 >=<=

因为 <>XML 语言的特殊字符 (用于定义标签,如 <where><if>),直接写 zone_spacing >= #{zoneSpacingMin} 会导致 XML 解析器报错,无法识别该语法,因此需要通过「转义」或「CDATA 包裹」两种方式规避。

二、mapper.xml>=<= 的两种正确固定写法(常用)

写法1:使用 <![CDATA[]]> 包裹(推荐,直观易懂)

CDATA 块的作用是告诉 XML 解析器:「块内的内容是纯文本,无需解析标签,直接原样保留」,适合所有特殊字符场景。

xml 复制代码
<select id="getTrafficZoneFlow" resultMap="TrafficZoneInfoSpaceingResultMap">
    select
        zone_id,
        target_zone_id,
        zone_spacing,
        project_plan_id
    from
        traffic_zone_spacing
    <where>
        1=1
        <if test="zoneId != null">
            and zone_id = #{zoneId}
        </if>
        <if test="targetZoneId != null">
            and target_zone_id = #{targetZoneId}
        </if>
        <!-- 大于等于(>=):用 CDATA 包裹 -->
        <if test="zoneSpacingMin != null">
            and zone_spacing <![CDATA[>=]]> #{zoneSpacingMin}
        </if>
        <!-- 小于等于(<=):用 CDATA 包裹 -->
        <if test="zoneSpacingMax != null">
            and zone_spacing <![CDATA[<=]]> #{zoneSpacingMax}
        </if>
    </where>
</select>
写法2:使用 XML 转义字符替换(兼容所有XML解析器)

>=<= 替换为 XML 预定义的转义字符,也能避免解析报错,常用转义对应关系如下:

运算符 含义 XML 转义字符
> 大于 &gt;
>= 大于等于 &gt;=
< 小于 &lt;
<= 小于等于 &lt;=
& &amp;
" 双引号 &quot;

对应 SQL 示例:

xml 复制代码
<select id="getTrafficZoneFlow" resultMap="TrafficZoneInfoSpaceingResultMap">
    select
        zone_id,
        target_zone_id,
        zone_spacing,
        project_plan_id
    from
        traffic_zone_spacing
    <where>
        1=1
        <if test="zoneId != null">
            and zone_id = #{zoneId}
        </if>
        <if test="targetZoneId != null">
            and target_zone_id = #{targetZoneId}
        </if>
        <!-- 大于等于(>=):使用转义字符 &gt;= -->
        <if test="zoneSpacingMin != null">
            and zone_spacing &gt;= #{zoneSpacingMin}
        </if>
        <!-- 小于等于(<=):使用转义字符 &lt;= -->
        <if test="zoneSpacingMax != null">
            and zone_spacing &lt;= #{zoneSpacingMax}
        </if>
    </where>
</select>

三、进阶:将 >=<= 改为动态变量(灵活切换运算符,呼应你之前的需求)

如果需要将固定的 >=<= 改为可动态切换的变量(支持 >>=<<=),核心要点如下:

  1. 运算符必须用 ${} 拼接(#{} 会加引号,导致 SQL 语法错误)。
  2. <![CDATA[${运算符变量}]]> 包裹 ${},避免 XML 解析报错。
  3. Java 层做白名单校验,防止 SQL 注入。
完整示例(动态运算符)
1. DTO 新增运算符参数(带白名单校验)
java 复制代码
import java.util.Arrays;

public class TrafficZoneFlowQueryDTO {
    private Integer zoneId;
    private Integer targetZoneId;
    private Integer zoneSpacingMin;
    private Integer zoneSpacingMax;
    // 新增:小于等于/小于 运算符(默认 <=)
    private String zoneSpacingMaxOp = "<=";
    // 新增:大于等于/大于 运算符(默认 >=)
    private String zoneSpacingMinOp = ">=";

    // Getter/Setter 省略
    
    // 白名单校验:限制合法运算符,防止 SQL 注入
    public void setZoneSpacingMinOp(String zoneSpacingMinOp) {
        String[] validOps = {">", ">="};
        this.zoneSpacingMinOp = Arrays.asList(validOps).contains(zoneSpacingMinOp) 
            ? zoneSpacingMinOp : ">=";
    }

    public void setZoneSpacingMaxOp(String zoneSpacingMaxOp) {
        String[] validOps = {"<", "<="};
        this.zoneSpacingMaxOp = Arrays.asList(validOps).contains(zoneSpacingMaxOp) 
            ? zoneSpacingMaxOp : "<=";
    }
}
2. mapper.xml 动态拼接运算符
xml 复制代码
<select id="getTrafficZoneFlow" resultMap="TrafficZoneInfoSpaceingResultMap">
    select
        zone_id,
        target_zone_id,
        zone_spacing,
        project_plan_id
    from
        traffic_zone_spacing
    <where>
        1=1
        <if test="zoneId != null">
            and zone_id = #{zoneId}
        </if>
        <if test="targetZoneId != null">
            and target_zone_id = #{targetZoneId}
        </if>
        <!-- 动态大于/大于等于:CDATA 包裹 ${zoneSpacingMinOp} -->
        <if test="zoneSpacingMin != null">
            and zone_spacing <![CDATA[${zoneSpacingMinOp}]]> #{zoneSpacingMin}
        </if>
        <!-- 动态小于/小于等于:CDATA 包裹 ${zoneSpacingMaxOp} -->
        <if test="zoneSpacingMax != null">
            and zone_spacing <![CDATA[${zoneSpacingMaxOp}]]> #{zoneSpacingMax}
        </if>
    </where>
</select>

四、总结

  1. mapper.xml 中不能直接写 >=<=,需用「<![CDATA[]]> 包裹」或「XML 转义字符」。
  2. 固定运算符场景优先选 <![CDATA[]]>,直观易维护。
  3. 需灵活切换运算符时,用 ${} 拼接+Java 白名单校验,兼顾灵活性和安全性。
  4. 核心避坑:运算符拼接用 ${},数据传参用 #{},特殊字符用 <![CDATA[]]> 包裹。
相关推荐
问水っ1 天前
Qt Creator快速入门 第三版 第17-2章 XML
xml
独断万古他化1 天前
【MyBatis 深度解析】注解操作与 XML 配置:增删改查全流程实现
xml·java·spring·mybatis
odoo中国1 天前
如何在 Odoo 19 中加载演示数据
xml·csv·odoo·odoo 19·odoo 演示数据加载
web守墓人3 天前
【前端】ikun-pptx编辑器前瞻问题五:pptx中的xml命名空间
xml·前端
h7ml3 天前
企业微信回调模式解析:从XML到POJO的自定义JAXB编解码器设计
xml·java·企业微信
Full Stack Developme3 天前
达梦(DM8)对 JSON 与 XML 的使用教程
xml·数据库·json
chilavert3184 天前
技术演进中的开发沉思-304计算机原理:XML
xml·计算机原理
程序猿零零漆6 天前
Spring之旅 - 记录学习 Spring 框架的过程和经验(十一)基于XML方式、注解的声明式事务控制、Spring整合Web环境
xml·学习·spring
科雷软件测试6 天前
推荐几个常用的校验yaml、json、xml、md等多种文件格式的在线网站
xml·html·md·yaml