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

gbase8s之MyBatis批量update问题

源代码

<update id="updateDynamicTableData"><foreach collection="mapList" item="map" separator=";">UPDATE ${tableName} SET<foreach collection="map" item="value" index="key" separator=",">${key}=#{value}  <!-- 注意:${key}需防注入 --></foreach>WHERE ARCHIVAL_CODE = #{map.ARCHIVAL_CODE}</foreach>
</update>

报错:

从错误信息和代码来看,问题出在 处理 NULL 值时 MyBatis 无法确定 JDBC 类型。具体分析如下:

问题原因

  1. NULL 值处理问题

    • 当 map 中的值为 null 时,MyBatis 无法自动推断 JDBC 类型(错误信息:Error setting null for parameter

    • 批量更新时(2条数据),只要有一条记录包含 NULL 值就会触发此错误

  2. 批量更新差异

    • 单条数据能成功是因为:可能该条数据的所有字段值都非 NULL

    • 两条数据失败是因为:第二条数据包含 NULL 值字段

解决方案

方法 1:指定 NULL 值的 JDBC 类型(推荐)

修改动态 SQL,为每个参数添加 jdbcType 配置:

<update id="updateDynamicTableData"><foreach collection="mapList" item="map" separator=";">UPDATE ${tableName} SET<foreach collection="map" item="value" index="key" separator=",">${key}=#{value, jdbcType=VARCHAR}  <!-- 添加jdbcType --></foreach>WHERE ARCHIVAL_CODE = #{map.ARCHIVAL_CODE}</foreach>
</update>

说明

  • jdbcType=VARCHAR 是示例,实际需根据字段类型选择:

    • 数字字段:jdbcType=NUMERIC

    • 日期字段:jdbcType=TIMESTAMP

    • 通用类型:jdbcType=OTHER

方法 2:全局配置 NULL 值处理

在 MyBatis 配置文件中添加:

<settings><!-- 指定 NULL 值的默认 JDBC 类型 --><setting name="jdbcTypeForNull" value="NULL"/>
</settings>

这会为所有 NULL 值统一设置 jdbcType=NULL

方法 3:接口参数指定类型

修改 DAO 接口,明确字段类型:

void updateDynamicTableData(@Param("mapList") List<Map<String, Object>> mapList,@Param("tableName") String tableName
);
#虽然不能直接解决,但可配合其他方案使用。

为什么单条成功、多条失败?

  • 单条数据:可能所有字段值恰好都非 NULL,无需处理类型推断

  • 多条数据:只要有一条记录包含 NULL 值字段,MyBatis 就需要处理类型映射,此时:

// 示例数据
List<Map> mapList = Arrays.asList({ "NAME": "张三", "AGE": 25 },             // 无NULL{ "NAME": null, "ADDRESS": "北京" }       // 包含NULL
);

第二条的 NAME=null 触发了类型推断错误。

完整修正方案(推荐)

关键点

  1. 确保 separator=","(内层循环用逗号分隔)

  2. 所有 #{value} 必须指定 jdbcType

  3. 动态字段 ${key} 需防范 SQL 注入(确保来源可信)

实际开发中,建议创建字段类型映射表,根据 ${key} 动态设置对应的 jdbcType


文章转载自:

http://uOYj2d0c.xqbbc.cn
http://tuEdbfym.xqbbc.cn
http://hGkzT7H3.xqbbc.cn
http://agSRxQUP.xqbbc.cn
http://y5VWuOsw.xqbbc.cn
http://o8MdGx3Q.xqbbc.cn
http://zKLY16wM.xqbbc.cn
http://d0PAA8CB.xqbbc.cn
http://QLUBm34r.xqbbc.cn
http://RwDe74B0.xqbbc.cn
http://FNV1zCAj.xqbbc.cn
http://07HCH5dW.xqbbc.cn
http://nBe55WwO.xqbbc.cn
http://Sl5ZPUfJ.xqbbc.cn
http://N8XS750e.xqbbc.cn
http://8NI6M4jS.xqbbc.cn
http://buLHoNrX.xqbbc.cn
http://shW6ZFlS.xqbbc.cn
http://zBNm2Jeu.xqbbc.cn
http://hgOHEIyV.xqbbc.cn
http://mffEnJxi.xqbbc.cn
http://1HFMpqor.xqbbc.cn
http://IUJKsIBX.xqbbc.cn
http://RhrT8aL5.xqbbc.cn
http://S9fjqbct.xqbbc.cn
http://ZKr4NAcr.xqbbc.cn
http://i7Kso1nz.xqbbc.cn
http://y0WfGM3R.xqbbc.cn
http://AiboASWi.xqbbc.cn
http://3nFa1LyW.xqbbc.cn
http://www.dtcms.com/a/248677.html

相关文章:

  • WPF--Application.Current.Dispatcher.BeginInvoke
  • 人工智能之数学基础:如何将二次型转换为标准型?
  • QMainWindow、QDialog 和 QWidget区别
  • 一文读懂:晶振不同等级的差异及对应最佳应用场景
  • leetcode 2616. 最小化数对的最大差值 中等
  • 软考 系统架构设计师系列知识点之杂项集萃(88)
  • springboot+vue大文件断点续传
  • 前端JavaScript面试题(2)
  • Promise(async、await)
  • 非本地地址调用摄像头需要https
  • Coze扣子 - AI生成数字人口播视频
  • 多环境开发配置,Spring boot
  • 【leetcode】101. 对称二叉树
  • Mysql 忘记密码后如何修改
  • 长春光博会 | 麒麟信安:构建工业数字化安全基座,赋能智能制造转型升级
  • 零基础学前端-传统前端开发(第四期-JS基础-运算)
  • sqlserver存储过程中入参使用JSON
  • redis穿透、击穿、雪崩
  • linux alignment fault对齐造成设备挂死问题定位梳理
  • 代码训练LeetCode(34)文本左右对齐
  • 行为模式-迭代器模式
  • 基于sample_aiisp再创建一路 h264编码流,和jpg的编码流
  • vue中的三种插槽方式
  • ABP vNext + OpenIddict:自定义 OAuth2/OpenID Connect 认证策略
  • 如何从 Windows 11 或 10 远程访问 Ubuntu 24.04 或 22.04 桌面
  • 使用 C++ 和 OpenCV 构建智能停车场视觉管理系统
  • Linux NFS服务器配置
  • JavaScript数组方法总结
  • 每日Prompt:Steve Winter风格插画
  • PyTorch框架-自动微分模块