MyBatis处理NULL值的核心是识别、区分与按业务意图转化,关键在查询映射(用包装类型+显式jdbcType)、更新控制(动态SQL过滤null)、参数清洗(字符串"null"转真null)及空值语义统一(Optional/空对象)。

MyBatis 处理 SQL 中的 NULL 值,核心不是“消灭 null”,而是让 null 可识别、可区分、可按业务意图转化。关键在三处:查询结果映射、更新语句生成、参数传入判断。下面分场景说清楚。
查询结果中正确接收数据库 NULL
数据库字段为 NULL 时,Java 层能否安全接住,取决于类型声明和映射配置:
- 实体类字段必须用包装类型(Long、Integer、String等),不能用 long、int、boolean 等基本类型——否则查到 NULL 会直接抛异常(如 PostgreSQL 的 Bad value for type long)
- 在
<resultMap>中,为可能为 NULL 的列显式声明jdbcType,例如:<result column="email" property="email" jdbcType="VARCHAR"/> - 若需区分“数据库 NULL”和“数据库存了空字符串”,SQL 层主动转换更可靠,比如:
SELECT COALESCE(nick_name, '__NULL__') AS nick_name FROM user,再在 Java getter 中解析标记
更新操作中避免误把 null 写进数据库
默认情况下,MyBatis 会把 Java 对象里的 null 字段原样转成 SQL 的 SET email = NULL,这常导致非预期覆盖。应按需控制:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 用动态 SQL 的
<if test="email != null">包裹字段赋值,只更新非空字段 - 配合
<set>标签自动处理逗号和空格,防止语法错误 - 若使用注解方式,可用
@UpdateProvider在 Java 中拼接条件化 SQL,逻辑更清晰
传参时识别并清洗“假 null”
前端或中间层传来的 “null” 很可能是字符串 "null",而非真正的 null,导致 MyBatis 的 test="name == null" 判断失效:
立即学习“Java免费学习笔记(深入)”;
- 在 Controller 或 Service 层提前做清洗:
if ("null".equalsIgnoreCase(name)) name = null; - Mapper 接口参数加
@Param注解,XML 中明确写#{name, jdbcType=VARCHAR},避免类型推断歧义 - 必要时在 SQL 层用
IFNULL(name, '')或COALESCE(name, '')统一兜底
统一空值语义,不依赖硬编码判空
避免满屏 if (user == null),把空值策略外提:
- 对单对象查询(如
selectOne),一律用Optional.ofNullable(mapper.selectById(id))包装,后续用.map()、.filter()、.orElse(...)表达业务含义 - 根据场景选 fallback:缺省值(
orElse("游客"))、抛异常(orElseThrow(NotFoundException::new))、跳过(filter(Objects::nonNull)) - 复杂场景可定义空对象,如
User.EMPTY或 Builder 构建默认实例,保持调用链不中断

















