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

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://www.xdnf.cn/news/14055.html

相关文章:

  • 中科院1区|IF10+:加大医学系团队利用GPT-4+电子病历分析,革新肝硬化并发症队列识别
  • 轻量级密码算法LED的C语言实现(无第三方库)
  • Ubuntu 24.04.2 LTS Python 人工智能Ai视觉模型
  • 使用php对navicat查看数据库密码?
  • 漏洞(网络空间安全真相)
  • 开源模型应用落地-工具使用篇-从零开始搭建Qdrant Web UI-可视化管理工具-Windows(十)
  • Linux 中 “/dev/null” 有什么作用 ?
  • OpenWrt:让OpenWrt支持USB声卡
  • 从喵喵喵到泄露Prompt:提示词注入攻击全解析
  • 【面板数据】中国与世界各国新能源汽车进出口数据-分类别与不分类别(2017-2024年)
  • UE5.5构建iOS失败但没有显式错误信息的问题
  • sharepoint 共享excel,如何实现某个 sheet 别人只读,但是另一个 sheet 可以编辑
  • 临时文件夹大量0字节xml问题排查
  • 在pyCharm中创建新的conda环境
  • 北斗导航 | 基于MATLAB的卫星导航单点定位算法(卡尔曼滤波增强)
  • 人工智能时代汽车营销如何创新突破?云徙科技汽车营销智能体助力车企立足数智化转型
  • Day53 Python打卡训练营
  • Github指南-Add .gitignore和Choose a license
  • 【C#】针对System.Drawing.Bitmap的压缩
  • python从环境变量和配置文件中获取配置参数
  • C#连接SQLServer数据库异常分析处理
  • 磁盘配额管理
  • django restframework 在serializer里 通过context设置session
  • HashMap vs LinkedHashMap
  • SpringMVC 常用注解及页面跳转方式(面试)
  • vue前端项目打包和部署
  • Vue3 + TypeScript 操作第三方库(Element Plus 的 ElTable)的内部属性
  • SQL Server 修改数据库名及物理数据文件名
  • 性能测试——搭建Prometheus+Grafana平台
  • linux学习慕课版 第一章 Linux 文件与目录学习笔记