MyBatis-Plus 查询结果全是 null,但条数正确:原因与排查办法

拾柒
拾柒
发布时间:2026-08-22 | 122人浏览过
原创

前言

MyBatis-Plus 查询“条数没问题、结果却全是 null”时,很多人第一反应是 SQL 写错了,但这类问题往往出在结果映射阶段,而不是查询本身。本文用一个 `Student` 示例拆开说明默认驼峰规则如何导致字段失配,再结合 Bean 定义和全局配置给出排查顺序,方便你快速判断该改实体命名、补齐访问方法,还是直接调整映射配置。

在 MyBatis-Plus 里,selectList(null) 能查到记录数,却打印出一串 null,这种现象很容易让人先怀疑 SQL 或 Mapper 写错了。实际上,这类问题大多发生在“查出来之后如何装配成对象”这一步。下面结合一个 Student 示例,把现象、根因和排查方式拆开说清楚,顺着看完基本就能判断问题到底出在字段命名、Bean 定义,还是框架配置上。

问题现象:查询条数对了,但列表元素全是 null

先看出问题的代码。自定义的 StudentMapper 继承了 BaseMapper:

public interface StudentMapper extends BaseMapper<Student> {
}

调用 selectList 后,列表长度正常,但逐条打印却全是 null:

@RequestMapping("/testmybatisplus")
@ResponseBody
public void testmybatisplus() {
    System.out.println("===1===");
    List<Student> list = studentMapper.selectList(null);
    //Assert.isTrue(5 == list.size(), "");
    list.forEach(System.out::println);
}

这类现象有一个明显特征:SQL 执行本身通常没有报错,返回记录数也对,比如查出 5 条,就得到 5 个 null。这说明“查询”大概率成功了,异常点更可能出现在“结果映射”阶段。

根因分析:默认驼峰映射与字段命名不匹配

问题的核心,通常在于数据库字段名、Java Bean 属性名,以及 MyBatis-Plus 的默认映射规则三者没有对齐。

展示 MyBatis-Plus 默认驼峰映射与下划线实体字段不匹配的关系图
字段映射为何会失配数据库字段、默认驼峰规则与实体属性名不一致时,最容易出现“条数正常但结果为 null”的现象。

数据库表结构如下:

CREATE TABLE student(
   stu_id VARCHAR(50),
   stu_name VARCHAR(30),
   stu_sex VARCHAR(2),
   stu_age VARCHAR(4),
   stu_addr VARCHAR(50),
   stu_pwd VARCHAR(50)
)DEFAULT CHARSET=utf8;

而实体类写成了下划线风格:

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
    private String stu_id;
    private String stu_name;
    private String stu_sex;
    private String stu_age;
    private String stu_addr;
    private String stu_pwd;
}

MyBatis-Plus 默认开启下划线转驼峰映射,会把数据库中的 stu_id 识别成 Java 属性 stuId,stu_name 识别成 stuName。但当前实体类属性名却是 stu_id、stu_name 这种写法,结果就是框架在装配对象时找不到匹配属性。

于是就会出现一种看起来很怪的结果:记录行数统计正常,但每一行都没能正确映射成实体对象,最后打印出来就是一串 null。

解决办法一:统一实体命名,优先按驼峰方式映射

如果项目本身就是按 MyBatis-Plus 默认规则在跑,最省事的做法通常是把实体类属性改成标准驼峰命名,例如把 stu_id 改成 stuId,把 stu_name 改成 stuName。

按这种方式处理后,数据库字段仍然保留 stu_id、stu_name 也没问题,MyBatis-Plus 会按默认规则自动完成映射。需要明确主键或特殊字段时,再配合 @TableId、@TableField 等注解补充说明即可。

这也是大多数 Java 项目里更常见、后续维护成本更低的写法,因为它和 Java Bean 命名习惯一致,和 MyBatis-Plus 的默认配置也一致。

解决办法二:检查 Bean 的 setter/getter 和构造器是否可用

如果你已经确认字段命名没有问题,下一步就该检查实体类本身是否具备正常的赋值入口。

MyBatis-Plus 在映射结果时,需要通过反射给对象属性赋值。如果 Bean 缺少必要的 setter/getter,或者构造器、Lombok 注解没有按预期生效,同样可能导致映射失败,最终表现为查询结果异常甚至出现 null。

这里尤其要注意两点:

  • @Data、@NoArgsConstructor、@AllArgsConstructor 是否真的被 Lombok 正常处理;
  • IDE 或构建环境里是否存在 Lombok 插件、依赖或注解处理配置缺失的问题。

如果怀疑是这一层原因,最直接的验证方法就是临时手动补齐属性访问方法和无参构造器,再重新执行查询。

解决办法三:关闭驼峰映射,让字段按原名匹配

如果你的项目明确希望实体类继续使用 stu_id 这种下划线字段名,也可以从配置层面关闭 MyBatis-Plus 默认的驼峰映射。

配置如下:

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: false

其中:

  • org.apache.ibatis.logging.stdout.StdOutImpl 用于打印 MyBatis-Plus 执行的 SQL,便于确认实际执行语句和调试过程;
  • map-underscore-to-camel-case: false 用于关闭下划线转驼峰,让字段按原样映射。

这种方式适合已经大量使用下划线风格实体字段、短期内不方便统一调整代码的项目。但从长期维护角度看,配置改动会影响整个映射行为,改之前最好确认项目里其他实体是否依赖默认驼峰规则。

补充:Mapper XML 路径也要写对

虽然本文这个问题的重点在字段映射,但如果项目里同时使用 Mapper XML,也要确认扫描路径是否正确:

  • 如果 XML 放在 src/main/java 目录下,路径写成 classpath:/com/*/*/mapper/*Mapper.xml;
  • 如果 XML 放在 resource 目录下,路径写成 classpath:/mapper/**.xml。

路径写错不一定会直接造成“条数正确但对象为 null”,但会让排查过程变复杂,最好一并确认。

排查时可以按这三个方向快速定位

遇到 MyBatis-Plus 查询结果条数正常、元素却全是 null,可以按下面的顺序检查:

展示 MyBatis-Plus 返回 null 时的三步排查与修复路径
三步定位返回 null 的原因排查时按“命名规则、Bean 可写性、全局配置”三个方向依次确认,通常能很快定位问题。
  1. 先看实体类字段名是不是仍然写成了 stu_id 这种下划线风格,而项目又启用了默认驼峰映射;
  2. 再看 Bean 的 setter/getter、无参构造器、Lombok 注解处理是否正常;
  3. 最后检查是否需要通过 map-underscore-to-camel-case: false 调整全局映射规则。

大多数情况下,第一项就是直接原因。只要把数据库字段、实体属性和框架配置三者统一起来,这个问题通常很快就能解决。

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表