jstAPI.ognl

本文介绍了jstAPI.ognl作为对象导航工具的功能及其API使用方法,特别是getValue方法,该方法用于通过传入的数据对象和ognl表达式获取对应的值。

jstAPI.ognl是对象导航工具

API

  • getValue
    • 获取对象的值
    • 参数:
      • data: {Object} 数据对象
      • ognl: {String} ognl表达式
    • 返回值: {*|null}
<think>我们正在处理MyBatis中出现的`java.lang.IllegalArgumentException: invalid comparison: java.util.Date and java.lang.String`异常。根据引用内容,该异常通常发生在MyBatis动态SQL中,当尝试将`java.util.Date`类型的属性与字符串(尤其是空字符串`''`)进行比较时。在MyBatis 3.3.0及更高版本中,这种比较会被视为非法操作。 ### 问题分析 - **根本原因**:在MyBatis的动态SQL条件判断(如`<if test="dateProperty != ''">`)中,如果`dateProperty`是`java.util.Date`类型,而`''`是字符串类型,MyBatis的OGNL表达式引擎会抛出此异常,因为不允许直接比较不同类型。 - **引用分析**: - 引用[1][2][3]指出,在MyBatis 3.3.0版本中,这是一个已知的bug,即当日期类型与空字符串进行比较时引发异常。 - 引用[4]展示了一个错误示例:在动态SQL中同时检查`date11 != null and date11 != ''`,其中`date11`是日期类型,而`''`是字符串。 ### 解决方案 #### ✅ 方法1:移除与空字符串的比较(推荐) 由于在MyBatis 3.3.0+版本中,日期类型与空字符串的比较会导致异常,因此我们只需移除与空字符串的比较,只保留非空检查。 **修改前**: ```xml <if test="date11 != null and date11 != ''"> AND time >= #{date11} </if> ``` **修改后**: ```xml <if test="date11 != null"> AND time >= #{date11} </if> ``` **理由**: - 当传入的日期参数为`null`时,条件不成立,不会添加该条件。 - 当传入的日期参数不为`null`时,条件成立,添加SQL片段。 - 由于日期类型不可能等于空字符串(`''`),因此无需检查空字符串。即使传入空字符串,在Java层也应该被转换为`null`或日期类型,所以这种检查在逻辑上也是多余的。 #### ✅ 方法2:降级MyBatis版本(不推荐) 如果由于某些原因必须保留与空字符串的比较,可以考虑降级到MyBatis 3.2.8或更低版本(引用[3]提到原工程使用3.2.8没有此问题)。但这不是推荐做法,因为新版本通常包含重要的安全更新和功能改进。 #### ✅ 方法3:在比较前将日期转换为字符串(备选) 如果确实需要检查空字符串(例如,参数可能是字符串也可能是日期),可以在OGNL表达式中将日期格式化为字符串,然后与空字符串比较。 ```xml <if test="date11 != null and date11.toString() != ''"> AND time >= #{date11} </if> ``` 或者使用`<bind>`标签: ```xml <bind name="date11Str" value="date11 != null ? date11.toString() : null" /> <if test="date11Str != null and date11Str != ''"> AND time >= #{date11} </if> ``` > **注意**:此方法会稍微增加复杂度,且需要确保`toString()`的格式符合预期(通常返回的是默认的日期字符串格式,如`Wed Dec 31 18:00:00 CST 2023`),可能不适用于所有场景。 ### 最佳实践 1. **参数传递规范**: - 在Java层,确保传入MyBatis的日期参数是`java.util.Date`或`java.sql.Date`类型,而不是字符串。如果前端传递的是字符串,应在Service层将其转换为日期类型。 - 对于可能为空的日期参数,使用`null`表示未传递,而不是空字符串。 2. **动态SQL优化**: - 避免在动态SQL条件中混合类型比较。 - 只进行非空检查(`test="date != null"`)即可,因为日期类型没有“空值”的概念(除了`null`)。 3. **版本选择**: - 推荐使用MyBatis 3.5.0+版本,因为它修复了许多已知问题,并提供了更好的错误信息。 ### 错误示例修正 **错误代码**(引用[4]中的示例): ```xml <select id="findTrail" resultType="Trail" parameterType="Dog"> select * from trail where 1=1 <if test="date11 != null and date11 != ''"> and time >= #{date11} </if> <if test="date22 != null and date22 != ''"> and time <= #{date22} </if> and iot=#{iot} and dwfs=#{dwfs} </select> ``` **修正后**(移除空字符串比较): ```xml <select id="findTrail" resultType="Trail" parameterType="Dog"> select * from trail where 1=1 <if test="date11 != null"> and time >= #{date11} </if> <if test="date22 != null"> and time <= #{date22} </if> and iot=#{iot} and dwfs=#{dwfs} </select> ``` ### 总结 - **根本解决**:移除动态SQL条件中日期类型与空字符串(`''`)的比较,只保留`null`检查。 - **深层原因**:MyBatis 3.3.0+版本加强了OGNL表达式的类型检查,禁止不同类型之间的比较操作。 - **预防措施**:在Java层统一参数类型,避免将字符串与日期类型混合使用。 --- ### 相关问题 1. 如何在MyBatis中安全地比较两个日期类型? 2. MyBatis动态SQL中还有哪些常见的类型不匹配问题? 3. 如何自定义MyBatis类型处理器(TypeHandler)来处理日期格式? 4. 在MyBatis中,如何优雅地处理日期范围查询? [^1]: 引用自站内引用[1] [^2]: 引用自站内引用[2] [^3]: 引用自站内引用[3] [^4]: 引用自站内引用[4]</think>### 解决 MyBatis 中 "invalid comparison: java.util.Date and java.lang.String" 异常 #### 🔍 问题根源分析 1. **类型冲突**:在 MyBatis 动态 SQL 中直接比较 `java.util.Date` 和 `java.lang.String` 类型(如 `refundTime != ''`) 2. **版本特性**:MyBatis 3.3.0+ 版本强化了类型检查,禁止不同类型比较(旧版本如 3.2.8 无此限制)[^2][^3] 3. **常见错误场景**: ```xml <!-- 错误示例:Date 类型 vs 空字符串 --> <if test="createTime != null and createTime != ''"> AND create_time = #{createTime} </if> ``` --- ### ✅ 终极解决方案 #### 方案1:移除空字符串检查(推荐⭐) ```xml <if test="createTime != null"> AND create_time = #{createTime} </if> ``` **优势**: - 完全兼容所有 MyBatis 版本 - 符合逻辑:Date 类型只需检查 `null`,无需检查空字符串 - 修复案例:某项目移除 `!= ''` 后异常消失[^2][^3] #### 方案2:降级 MyBatis 版本(临时方案) ```xml <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.2.8</version> <!-- 无此问题的旧版本 --> </dependency> ``` > **注意**:仅建议临时使用,新版本有安全性和性能优化 #### 方案3:类型转换法(复杂场景) ```xml <bind name="dateString" value="@java.text.SimpleDateFormat@('yyyy-MM-dd').format(createTime)" /> <if test="paramString != null and dateString == paramString"> ... </if> ``` --- ### 🛠 最佳实践 1. **参数预处理**(Java 层): ```java // 在 Service 层转换字符串为 Date public List<Data> query(String dateStr) { Date date = StringUtils.isBlank(dateStr) ? null : new SimpleDateFormat("yyyy-MM-dd").parse(dateStr); return mapper.query(date); } ``` 2. **XML 优化写法**: ```xml <!-- 安全写法:只检查 null --> <if test="startDate != null"> AND create_time >= #{startDate} </if> <if test="endDate != null"> AND create_time <![CDATA[ <= ]]> #{endDate} </if> ``` 3. **防御性编程**: ```xml <!-- 添加版本兼容检查 --> <choose> <when test="_databaseId == 'mysql' and startDate != null"> AND DATE(create_time) = #{startDate} </when> </choose> ``` --- ### ⚠ 错误示例修正 **原错误代码** [^4]: ```xml <if test="date11 != null and date11 != ''"> <!-- 触发异常 --> AND time >= #{date11} </if> ``` **修正后**: ```xml <if test="date11 != null"> <!-- 移除空字符串检查 --> AND time >= #{date11} </if> ``` --- ### 版本兼容性指南 | MyBatis 版本 | 是否允许 Date/String 比较 | 建议操作 | |--------------|----------------------------|------------------------| | < 3.3.0 | ✅ 允许 | 无需修改 | | ≥ 3.3.0 | ❌ 禁止 | 移除 `!= ''` 检查 | | ≥ 3.5.6 | ❌ 禁止 | 使用类型统一策略 | > 关键原则:**始终保证比较操作数的类型一致** --- ### 相关问题 1. MyBatis 3.3.0 版本升级有哪些破坏性变更? 2. 如何在动态 SQL 中安全处理日期范围查询? 3. MyBatis 类型处理器(TypeHandler)如何解决类型转换问题? 4. 除了日期类型,MyBatis 还有哪些常见的 OGNL 表达式陷阱? [^1]: 引用自站内引用[1] [^2]: 引用自站内引用[2] [^3]: 引用自站内引用[3] [^4]: 引用自站内引用[4]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值