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[]]> 包裹。
相关推荐
历程里程碑9 小时前
Protobuf vs JSON vs XML:小白该怎么选?
xml·大数据·数据结构·elasticsearch·链表·搜索引擎·json
那个失眠的夜1 天前
Mybatis延迟加载策略
xml·java·数据库·maven·mybatis
mfxcyh1 天前
基于xml、注解、JavaConfig实现spring的ioc
xml·java·spring
vortex52 天前
SOAP 协议中的 XML 外部实体注入(XXE)漏洞
xml·网络安全·渗透测试
Dxy12393102162 天前
Python如何对XML进行格式化
xml·python
2501_930707783 天前
使用C#代码将 HTML 转换为 PDF、XPS 和 XML
xml·pdf
研來如此7 天前
tinyxml2 常用读取接口对照表
xml·c++·tinyxml2
pupudawang8 天前
使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法
xml·spring·logback
jf加菲猫9 天前
第10章 数据处理
xml·开发语言·数据库·c++·qt·ui
Java成神之路-9 天前
序列化协议全解析:XML、SOAP、JSON 与 Protobuf 实战对比及 Protobuf 演进方案
xml·json