在 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 的默认映射规则三者没有对齐。

数据库表结构如下:
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,可以按下面的顺序检查:

- 先看实体类字段名是不是仍然写成了
stu_id这种下划线风格,而项目又启用了默认驼峰映射; - 再看 Bean 的
setter/getter、无参构造器、Lombok 注解处理是否正常; - 最后检查是否需要通过
map-underscore-to-camel-case: false调整全局映射规则。
大多数情况下,第一项就是直接原因。只要把数据库字段、实体属性和框架配置三者统一起来,这个问题通常很快就能解决。









