🧐 MyBatis 报错:invalid comparison: java.util.Date and java.lang.String 的原因及解决方法
在使用 MyBatis 进行数据库查询时,我们有时会遇到一个让人摸不着头脑的异常信息:
nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
### Cause: java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
这篇文章就来分析这个错误的原因,并提供解决方案。
📌 问题背景
我们在 Java 实体类中定义了 Date
类型的时间字段,例如:
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTimeStart;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTimeEnd;
对应的 Mapper XML 中写了类似这样的判断逻辑:
<if test="createTimeStart != null and createTimeStart != '' and createTimeEnd != null and createTimeEnd != ''">
AND create_time > #{createTimeStart} AND create_time < #{createTimeEnd}
</if>
虽然代码看起来没问题,但运行时却报出了类型比较异常。
❗根本原因
关键在于这一段条件判断:
test="createTimeStart != null and createTimeStart != ''"
这里试图将 Date
类型与空字符串 ''
做比较,这是非法操作!
Java 中不同类型之间无法直接进行比较,MyBatis 在解析 <if>
条件表达式时就会抛出:
java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String
✅ 正确写法
我们应该只对 Date
类型做非空判断:
<if test="createTimeStart != null and createTimeEnd != null">
AND create_time BETWEEN #{createTimeStart} AND #{createTimeEnd}
</if>
或者保留原始写法,去掉对空字符串的判断:
<if test="createTimeStart != null and createTimeEnd != null">
AND create_time > #{createTimeStart} AND create_time < #{createTimeEnd}
</if>
💡 小贴士
BETWEEN
更简洁清晰,推荐使用。- 确保你的 Java 参数确实是
Date
或LocalDateTime
类型。 - 如果你用的是 Java 8 及以上,建议引入
mybatis-typehandlers-jsr310
支持新时间 API。 - 数据库字段应为
DATETIME
/TIMESTAMP
类型,不要使用字符串存储日期。
🧾 总结
问题 | 原因 | 解决方案 |
---|---|---|
invalid comparison: Date and String | 对 Date 使用了 != '' 判断 | 删除对空字符串的判断,仅保留 != null |