🐛 问题现象
在使用 MyBatis-Plus 多租户插件(TenantLineInnerInterceptor)时,发现以下代码片段在某些位置会报错:
<if test="bo.params.beginTime!=null and bo.params.beginTime!='' and bo.params.endTime!=null and bo.params.endTime!=''">
AND (t1.up_shelf_time between #{bo.params.beginTime} and #{bo.params.endTime})
</if>
报错信息:
Caused by: net.sf.jsqlparser.parser.ParseException: Encountered unexpected token: "AND" "AND"
🔍 问题原因
经过排查,发现这是 MyBatis-Plus 多租户插件的一个解析bug,具体原因:
- 插件解析顺序敏感:TenantLineInnerInterceptor 在解析SQL时对条件位置敏感
- JSqlParser 限制:底层使用的 SQL 解析器对复杂条件拼接处理存在缺陷
- 条件组合冲突:当多个动态条件组合时,特定位置的 BETWEEN 条件会引发解析错误
✅ 解决方案
方案一:调整条件位置(当前有效)
将时间条件往前放置即可解决:
WHERE 1=1
<!-- 时间条件必须放在前面 -->
<if test="bo != null and bo.params != null
and bo.params.beginTime != null and bo.params.beginTime != ''
and bo.params.endTime != null and bo.params.endTime != ''">
AND (t1.up_shelf_time between #{bo.params.beginTime} and #{bo.params.endTime})
</if>
<!-- 其他条件放在后面 -->
<if test="otherCondition != null">
AND other_condition = #{value}
</if>
方案二:避免使用 BETWEEN
使用独立的比较条件更稳定:
WHERE 1=1
<if test="bo != null and bo.params != null
and bo.params.beginTime != null and bo.params.beginTime != ''
and bo.params.endTime != null and bo.params.endTime != ''">
AND t1.up_shelf_time >= #{bo.params.beginTime}
AND t1.up_shelf_time <= #{bo.params.endTime}
</if>
📝 注意事项
- 这不是代码逻辑问题,而是 MyBatis-Plus 插件的解析bug
- 条件顺序影响结果:某些条件需要放在特定位置才能正常工作
- XML 转义重要:始终使用
>=和<=代替>=和<= - NULL 值处理:注意时间字段为 NULL 时的处理逻辑
🚨 影响范围
- MyBatis-Plus 版本:3.4.3+(具体版本待确认)
- 仅影响使用 TenantLineInnerInterceptor 多租户插件的场景
- 主要涉及包含 BETWEEN 条件的动态SQL
📋 后续行动
- 在团队文档中记录此问题
- 考虑升级 MyBatis-Plus 版本测试是否修复
- 如持续出现,向 MyBatis-Plus 团队提交issue
- 在新项目中优先使用方案二的写法