1. 为什么需要关注mapper.xml中的比较运算符
在MyBatis框架的实际开发中,mapper.xml文件是我们与数据库交互的核心枢纽。特别是涉及到数值范围查询时,大于等于(>=)和小于等于(<=)这类比较运算符的使用频率极高。但很多开发者在处理这些符号时会遇到XML语法冲突、SQL注入风险等问题。
上周排查一个生产环境Bug时,就发现因为mapper.xml中范围查询的符号处理不当,导致促销活动时间范围判断失效,直接造成数百万的损失。这个案例让我深刻意识到,这些看似简单的符号背后藏着不少技术细节。
2. 基础语法:XML中的特殊符号处理
2.1 原生符号的问题
在mapper.xml中直接使用>=和<=会导致XML解析错误,因为>和<是XML的保留字符。例如下面这种写法会直接报错:
xml复制<!-- 错误示例 -->
<select id="selectByRange" parameterType="map">
SELECT * FROM products
WHERE price >= #{minPrice} AND price <= #{maxPrice}
</select>
2.2 正确的转义写法
MyBatis官方推荐使用XML实体引用来替代这些特殊符号:
xml复制<!-- 正确写法 -->
<select id="selectByRange" parameterType="map">
SELECT * FROM products
WHERE price >= #{minPrice} AND price <= #{maxPrice}
</select>
对应的转义规则:
>转义为><转义为<&转义为&
注意:在CDATA区块中可以直接使用原生符号,但不推荐这种做法,因为会降低代码可读性
3. 高级用法:动态SQL中的范围查询
3.1 使用的注意事项
虽然CDATA可以绕过转义问题:
xml复制<select id="selectByRange">
<![CDATA[
SELECT * FROM products
WHERE price >= #{minPrice} AND price <= #{maxPrice}
]]>
</select>
但这种写法有两个隐患:
- 部分IDE会失去语法高亮和提示
- 如果内部包含其他MyBatis标签(如
)会导致解析混乱
3.2 结合标签的最佳实践
推荐将转义符号与动态SQL结合:
xml复制<select id="selectByRange" parameterType="map">
SELECT * FROM products
<where>
<if test="minPrice != null">
AND price >= #{minPrice}
</if>
<if test="maxPrice != null">
AND price <= #{maxPrice}
</if>
</where>
</select>
4. 常见问题排查指南
4.1 符号转义失效的情况
当遇到如下错误时:
code复制org.xml.sax.SAXParseException: The entity "gt" was referenced, but not declared
解决方案:
- 检查XML文件头是否正确定义:
xml复制<?xml version="1.0" encoding="UTF-8"?>
- 确认没有误将
>写成>(缺少分号)
4.2 数值边界处理技巧
在处理前端输入时(比如uni-easyinput限制只能输入大于等于0的正数),建议在mapper层再做一次校验:
xml复制<select id="selectValidProducts">
SELECT * FROM products
WHERE price >= 0
<if test="maxPrice != null and maxPrice >= 0">
AND price <= #{maxPrice}
</if>
</select>
4.3 性能优化建议
对于大数据表的范围查询,应该:
- 为范围查询字段建立索引
- 配合分页使用:
xml复制<select id="selectByRangeWithPage">
SELECT * FROM products
WHERE price >= #{minPrice}
AND price <= #{maxPrice}
LIMIT #{offset}, #{pageSize}
</select>
5. 实际开发中的经验总结
-
代码审查重点:在CR时特别检查mapper.xml中的比较运算符,这是高频出错点
-
测试技巧:边界值测试要包含:
- 最小值-1
- 最小值
- 最大值
- 最大值+1
-
IDE配置:
- 在IntelliJ IDEA中安装MyBatis插件
- 配置Live Template快速生成转义符号
-
安全防范:永远不要这样写(SQL注入风险):
xml复制<!-- 危险示例 -->
WHERE price >= ${minPrice}
应该始终使用#{}预处理:
xml复制<!-- 安全写法 -->
WHERE price >= #{minPrice}
在最近的项目中,我们通过静态代码扫描工具,在CI流程中增加了对mapper.xml特殊符号的检查规则,将相关错误在合并前就拦截下来,效果非常显著。建议团队可以考虑类似的自动化检查方案。
