java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > MyBatis动态SQL数值0更新失效

MyBatis动态SQL中数值0更新失效问题解析与解决方案

作者:尽兴-

本文详细解析了MyBatis动态SQL中数值字段更新失效的问题,指出使用FastJSON的JSONObject接收入参时应避免混用字符串、数字判断,并提出两种解决方案,推荐采用数值字段最优方案,需要的朋友可以参考下

一、问题现象

业务场景为物料库存更新接口,使用 FastJSON 的 JSONObject 接收入参,MyBatis 动态 SQL 通过 <if> 标签判断字段是否参与更新:

  1. 入参 newQuantity 传入数值 0(Integer 类型);
  2. XML 中判断条件:<if test="newQuantity != null and newQuantity != ''">
  3. 最终打印的执行 SQL 完全没有拼接 invt = #{newQuantity} 这一段,库存字段未更新;
  4. newQuantity 传入大于 0 的数字(如 2、5)时,SQL 正常拼接,更新逻辑生效。

二、根因分析

1. OGNL 表达式底层判定规则

MyBatis 的 <if test> 使用 OGNL 表达式做条件判断,当数字 0 与**空字符串 ''**做不等对比时:
0 != '' 的运算结果为 false
完整条件 newQuantity != null and newQuantity != '' 逻辑拆解:

2. 混用字符串、数字判断是核心误区

!= '' 是专门用于字符串类型的判空逻辑,用来过滤前端传过来的空字符串 ""
而库存、金额、单价、税额这类字段,存储类型为 Integer/BigDecimal,入参只会是 null 或数字,永远不会出现空字符串,强行叠加 != '' 判断会拦截数值 0。

3. 同类受影响字段

代码中所有金额、数值字段都存在相同隐患:
amount_inclusive_taxunit_pramount_taxamount_no_tax,当传入 0 时都会出现更新失效。

三、两种解决方案

方案 1:数值字段最优方案(推荐)

数字类型字段仅判断 null,直接删除 != '' 条件,不做空字符串校验:

<!-- 库存数量(Integer) -->
<if test="newQuantity != null">
    invt = #{newQuantity},
</if>
<!-- 含税金额(BigDecimal) -->
<if test="amount_inclusive_tax != null">
    amount_inclusive_tax = #{amount_inclusive_tax},
</if>

优势:逻辑简洁、无多余运算,完美兼容 0、正数、负数等所有数字场景。

方案 2:兼容字符串 + 数字混合入参场景

若字段存在同时接收字符串、数字的特殊场景,补充数字 0 的判断逻辑:

<if test="newQuantity != null and (newQuantity != '' or newQuantity == 0)">
    invt = #{newQuantity},
</if>

劣势:多一层逻辑判断,纯数值业务不推荐使用。

四、规范区分:什么时候用!= '',什么时候只用!= null

  1. 字符串字段(名称、编码、备注、地址)
    需要双重判断,过滤 null 和前端空字符串:
<if test="artiName != null and artiName != ''">
    arti_name = #{artiName},
</if>
  1. 数值字段(Integer、Long、BigDecimal、Double)
    仅判断非 null,禁止加 != ''
<if test="changeQuantity != null">
    invt = #{changeQuantity},
</if>

五、修正后完整 XML 示例

<update id="updateInvtQuantity" parameterType="com.alibaba.fastjson.JSONObject">
    UPDATE LCP_ARTI_MATN_HQZX
    SET
    <if test="newQuantity != null">
        invt = #{newQuantity},
    </if>
    <if test="amount_inclusive_tax != null">
        amount_inclusive_tax = #{amount_inclusive_tax},
    </if>
    <if test="unit_pr != null">
        unit_pr = #{unit_pr},
    </if>
    <if test="amount_tax != null">
        amount_tax = #{amount_tax},
    </if>
    <if test="amount_no_tax != null">
        amount_no_tax = #{amount_no_tax},
    </if>
    sysupdatedate = SYSDATE,
    sysupdateoruuid = #{syscreatoruuid},
    sysupdateoruuidname = #{syscreatoruuidname}
    WHERE matn_id = #{matnId}
    AND sysisdelete = '0'
</update>

六、总结避坑要点

  1. 数字字段不要混用空字符串判断 != '',会拦截数值 0;
  2. 严格区分字段类型,字符串双重判空、数值仅判 null;
  3. 开发完成后务必覆盖入参为 0 的场景做单元测试,避免库存清零、金额置零等业务逻辑失效;
  4. 打印 MyBatis 执行 SQL 日志辅助排查动态分支是否正常拼接。

以上就是MyBatis动态SQL中数值0更新失效问题解析与解决方法的详细内容,更多关于MyBatis动态SQL数值0更新失效的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文