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[]]> 包裹。
相关推荐
执明wa2 天前
Android RecyclerView 多类型, 多种 Item
android·xml·开发语言·设计模式·android studio
wl85112 天前
SAP CPI 教程004 如何通过groovy修改XML节点属性值
xml
码匠许师傅4 天前
【C++三方组件】TinyXML2:两个文件的极简 XML 解析器
xml·c++
yuzhiboyouye5 天前
my-batisPlus什么时候用xml什么时候用mapper自带的方法,这两种写法专业一点叫什么,什么场景分别使用
xml
筝筝ba6 天前
如何跳过FFDC
xml·linux·运维·服务器·网络
yuzhiboyouye7 天前
那xml对应的sql语法,列举一下
xml·数据库·sql
筝筝ba11 天前
OpenBMC 自动化测试中的多进程陷阱:从 Execute Process 返回异常到 output.xml 损坏问题分析
xml·linux·运维·服务器·网络
spencer_tseng16 天前
[j2cache ehcache.xml]/tmp/.ehcache-diskstore.lock (Permission denied)
xml·linux·python·ehcache·[j2cache
DevOpenClub17 天前
PDF 多格式解析如何避免混用输出:TEXT、HTML、XML 与 TAG 数据契约
xml·前端·数据库·pdf·html
Java小白笔记17 天前
MyBatis XML Mapper 标签与 CRUD 原理实战
xml·数据库·mybatis