1. 当Date遇上String:MyBatis动态SQL的经典陷阱
最近在项目里用MyBatis写动态SQL时,突然遇到个让人头皮发麻的报错:"invalid comparison: java.util.Date and java.lang.String"。这个错误来得莫名其妙,明明代码看起来很正常,怎么就突然抛异常了呢?相信不少朋友在判断日期字段是否为空时,都写过类似这样的代码:
xml复制<if test="createTime != null and createTime != ''">
AND create_time = #{createTime}
</if>
表面上看这个判断逻辑很合理:既要检查日期不为null,又要防止空字符串。但实际运行时,MyBatis会直接抛出类型比较异常。这是因为在OGNL表达式里,Date对象和String对象根本就不是一个世界的生物,强行比较就像让猫和狗用同一种语言交流,结果必然是鸡同鸭讲。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 深入理解OGNL的类型处理机制
2.1 OGNL的类型强制转换规则
OGNL(Object-Graph Navigation Language)是MyBatis用来解析动态SQL表达式的引擎。当它遇到比较操作时,会尝试进行类型转换以便比较。但对于Date和String这种完全不兼容的类型,OGNL会直接拒绝转换。
举个例子,当你写createTime != ''时,OGNL的处理流程是这样的:
- 发现左边是java.util.Date类型
- 右边是java.lang.String类型
- 尝试寻找类型转换器
- 发现没有合适的转换方式
- 抛出Invalid comparison异常
2.2 为什么Date不能和空字符串比较
这里有个常见的误解:开发者往往认为空字符串""可以表示"没有日期"。但实际上:
- 在Java中,Date是时间点的对象表示
- 空字符串""是纯粹的文本概念
- 两者在语义和存储结构上完全不同
就像你不能问"这个苹果等于红色吗"一样,Date和String属于不同维度的概念,比较它们本身就没有意义。
3. 正确的日期判空姿势
3.1 基础解决方案:只检查null
对于大多数场景,其实只需要检查Date
