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[]]> 包裹。
相关推荐
常利兵2 小时前
Android 字体字重设置:从XML到Kotlin的奇妙之旅
android·xml·kotlin
Predestination王瀞潞19 小时前
2.4 编码->W3C XML 1.0标准(W3C Recommendation):XML(Extensible Markup Language)
xml·前端
青槿吖2 天前
【保姆级教程】Spring事务控制通关指南:XML+注解双版本,避坑指南全奉上
xml·java·开发语言·数据库·sql·spring·mybatis
北京聚信万通科技有限公司2 天前
Odette OFTP2 Group1/2/3深度解读:PDX XML能力划分与选型指南
xml·edi·电子数据交换·as2·国产软件·oftp2
小趴蔡ha4 天前
如何将XML格式标注文件转换为YOLO格式进行目标检测训练(附代码)
xml·yolo·目标检测
__Yvan4 天前
解决ConstraintLayout中LinearLayout显示异常问题
android·xml·约束布局
weixin_307779134 天前
构建健壮的XML文档抓取与摘要流水线:Requests + urllib3.Retry + lxml 实践
xml·开发语言·python·算法·性能优化
kgduu5 天前
js之xml处理
xml·前端·javascript
aisifang005 天前
使用 Logback 的最佳实践:`logback.xml` 与 `logback-spring.xml` 的区别与用法
xml·spring·logback
小江的记录本6 天前
【Spring Boot—— .yml(YAML)】Spring Boot中.yml文件的基础语法、高级特性、实践技巧
xml·java·spring boot·后端·spring·spring cloud·架构