当前位置: 首页 > news >正文

MyBatis的xml中字符串类型判空与非字符串类型判空处理方式

orderNo != null 这种非字符串类型的判断,也能用 Java 静态方法来替代,比如用 Hutool 的 ObjectUtil.isNotNull()ObjectUtil.isNotEmpty()

我帮你把 字符串StrUtil.isNotBlank()非字符串ObjectUtil.isNotNull() 的完整 MyBatis updateById 版本写好,这样判断逻辑会很统一。


完整 Hutool 写法版本

<update id="updateById" parameterType="com.example.NursingProject">UPDATE nursing_project<set><if test="@cn.hutool.core.util.StrUtil@isNotBlank(name)">name = #{name},</if><if test="@cn.hutool.core.util.ObjectUtil@isNotNull(orderNo)">order_no = #{orderNo},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(unit)">unit = #{unit},</if><if test="@cn.hutool.core.util.ObjectUtil@isNotNull(price)">price = #{price},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(image)">image = #{image},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(nursingRequirement)">nursing_requirement = #{nursingRequirement},</if><if test="@cn.hutool.core.util.ObjectUtil@isNotNull(status)">status = #{status},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(createBy)">create_by = #{createBy},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(updateBy)">update_by = #{updateBy},</if><if test="@cn.hutool.core.util.StrUtil@isNotBlank(remark)">remark = #{remark},</if><if test="@cn.hutool.core.util.ObjectUtil@isNotNull(updateTime)">update_time = #{updateTime},</if></set>WHERE id = #{id}
</update>

对比优化

  • 原本 MyBatis 写法

    <if test="orderNo != null">...</if>
    

    需要区分字符串、数字、对象分别写不同条件。

  • 现在 Hutool 写法

    • 字符串StrUtil.isNotBlank()(避免空格也被当作有效值)
    • 数字/对象ObjectUtil.isNotNull()(仅判断 null,不管 0/false)

这样代码风格统一,可读性也更好。


这个现象其实是 MyBatis + OGNL 的自动类型推断 惹的祸。

你这里:

<if test="@cn.hutool.core.util.ObjectUtil@isNotNull(price)">price = #{price},
</if><if test="@cn.hutool.core.util.ObjectUtil@isNotNull(status)">status = #{status},
</if>

表面上看用的都是同一个 ObjectUtil.isNotNull(),但实际上 pricestatus 的运行时类型不一样:

字段Java 类型JSON 传值类型MyBatis 解析时的实际类型
priceBigDecimal50java.math.BigDecimal
statusInteger1java.lang.Long

为什么 status 变成 Long

MyBatis 在 JSON 反序列化(或者参数绑定)时,如果是整数值但没有显式指定类型,很多情况下会用 Long 表示(尤其是 Map 或动态 SQL 场景中)。
ObjectUtil.isNotNull(1L) 本身没问题,但在 OGNL 调用静态方法时,有些版本的 MyBatis/OGNL 会先尝试做类型转换(尤其是如果方法签名有重载或匹配不明确时),于是会触发 "Unable to convert type java.lang.Long to java.lang.CharSequence" 这种异常。


为什么 price 没事?

BigDecimal 类型在 OGNL 里不会被误判去做字符串转换,因为它本来就不是 CharSequence,且 ObjectUtil.isNotNull() 的签名 isNotNull(Object) 匹配得很干脆,没有触发额外的类型推断。


怎么解决?

最稳妥的方式就是 不要用静态方法去判断 null,直接用 OGNL 原生的 null 判断:

<if test="price != null">price = #{price},
</if><if test="status != null">status = #{status},
</if>

这样不涉及静态方法匹配,就不会出现 LongCharSequence 的问题。


如果你一定要用 ObjectUtil.isNotNull

<if test="@cn.hutool.core.util.ObjectUtil@isNotNull((Object)status)">status = #{status},
</if>

(Object) 是为了让 OGNL 不去尝试把 Long 当作别的类型匹配。


如果单纯比较性能,原生 != null 判断 会明显比 StrUtil.isNotBlank() 快。

原因很简单:

判断方式逻辑性能分析
!= null直接用 OGNL 判断对象是否为 null,属于一次简单的引用比较O(1) 操作,几乎没有额外开销
StrUtil.isNotBlank()Hutool 工具方法,需要静态方法调用 + 类型检查 + 遍历字符串判断空格至少多了方法调用开销 + 字符遍历(字符串越长耗时越多)

举个例子(粗略对比执行步骤):

1. != null

  • MyBatis OGNL:取值
  • JVM:引用地址是否为 null → true/false
  • 总耗时 ≈ 一次内存地址比较

2. StrUtil.isNotBlank()

  • MyBatis OGNL:加载 StrUtil

  • JVM:调用静态方法

  • 方法内部:

    1. 判断对象是否为 null
    2. 调用 String.length()
    3. 遍历每个字符判断是否为空格字符
  • 总耗时 ≈ 多次方法调用 + 字符遍历


结论

  • 非字符串类型!= null 是最优方案(少步骤、无额外逻辑)
  • 字符串类型 → 如果需要判断空字符串和全空格情况,那必须用 isNotBlank()(功能多,但慢一点)
  • 如果字符串允许空格或空值存储,不做空格判断,用 != null 会快很多

建议:

  • 数值、日期、枚举 → 全部用 != null
  • 字符串 → 如果必须去掉空格判断为空,才用 isNotBlank();否则也用 != null

http://www.lryc.cn/news/616046.html

相关文章:

  • 秋招春招实习百度笔试百度管培生笔试题库百度非技术岗笔试|笔试解析和攻略|题库分享
  • wordpress语言包制作工具
  • python正则表达式里面有特殊符号如何处理
  • 亚麻云之静态资源管家——S3存储服务实战
  • Day41--动态规划--121. 买卖股票的最佳时机,122. 买卖股票的最佳时机 II,123. 买卖股票的最佳时机 III
  • LeetCode 组合总数
  • AI质检数据准备利器:基于Qt/QML 5.14的图像批量裁剪工具开发实战
  • Python 2025:最新技术趋势与展望
  • Text2SQL 自助式数据报表开发(Chat BI)
  • 解决 .NET Core 6.0 + PostgreSQL 网站首次连接缓慢问题
  • 嵌入式软件分层架构的设计原理与实践验证(有限状态机理解及结构体封装理解)
  • spring-ai整合PGVector实现RAG
  • WinForm之TreeView控件
  • Baumer高防护相机如何通过YoloV8深度学习模型实现道路坑洼的检测识别(C#代码UI界面版)
  • [激光原理与应用-223]:机械 - 机加厂加工机械需要2D还是3D图?
  • jvm有哪些垃圾回收器,实际中如何选择?
  • 本地WSL部署接入 whisper + ollama qwen3:14b 总结字幕校对增强版
  • Code Exercising Day 10 of “Code Ideas Record“:StackQueue part02
  • 低版本 IntelliJ IDEA 使用高版本 JDK 语言特性的问题
  • IDEA 如何导入系统设置
  • 基于ECharts的智慧社区数据可视化
  • IDEA 快捷编辑指南
  • IntelliJ IDEA 2025.2 重磅发布
  • OneCode 3.0 可视化功能全面分析:从开发者到用户的全场景解析
  • [激光原理与应用-214]:设计 - 皮秒紫外激光器 - 电控设计,高精度、高可靠性与智能化的全链路方案
  • 【渲染流水线】[几何阶段]-[归一化NDC]以UnityURP为例
  • SpringMVC的知识点总结
  • JDBC的连接过程(超详细)
  • 【Python 工具人快餐 · 第 6 份】
  • Redis缓存穿透、缓存击穿、缓存雪崩