News
首页  -  资讯  - 
MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题
MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题 MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题 前言 在使用 MyBatis 进行资料库查询时,你是否遇到过这样的情况:明明 SQL 执行成功了,数据也查出来了,但返回的 Java 对象中,某些字段却是 null ?本文将从一个真实案例出发,深入剖析这个问题的根本原因,并给出三种处理方式,帮助你...

MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题 MyBatis 查询结果字段为 null?一文讲透下划线命名与驼峰映射问题 前言 在使用 MyBatis 进行资料库查询时,你是否遇到过这样的情况:明明 SQL 执行成功了,数据也查出来了,但返回的 Java 对象中,某些字段却是 null ?本文将从一个真实案例出发,深入剖析这个问题的根本原因,并给出三种处理方式,帮助你彻底搞懂 MyBatis 的结果映射机制。 一、问题场景 1.1 数据库表结构 假设我们有一张汽车表 t_car ,表结构如下: CREATE TABLE t_car ( id BIGINT AUTO_INCREMENT PRIMARY KEY, car_num VARCHAR ( 255 ), -- 车牌号 brand VARCHAR ( 255 ), -- 品牌 guide_price DECIMAL ( 10 , 2 ), -- 指导价 produce_time CHAR ( 10 ), -- 生产日期 car_type VARCHAR ( 255 ) -- 车辆类型 ); 表中的数据如下: id car_num brand guide_price produce_time car_type 1 京A88888 宝驹535 20.00 2025-10-11 燃油车 2 京A66666 劳斯莱斯泡影 300.00 2025-10-12 新能源 3 海A8888 宝马 30.00 2023-02-02 燃油车 ... ... ... ... ... ... 1.2 Java 实体类 对应的 Java 实体类 Car.java : public class Car { private Long id; private String carNum; // 对应数据库 car_num private String brand; private Double guidePrice; // 对应数据库 guide_price private String produceTime; // 对应数据库 produce_time private String carType; // 对应数据库 car_type // getter / setter / toString } 1.3 MyBatis Mapper 配置 Mapper 接口: public interface CarMapper { List selectAll () ; } Mapper XML 映射文件: < select id = "selectAll" resultType = "car" > SELECT * FROM t_car 1.4 查询结果异常 执行查询后,得到的结果如下: Car{ id = 3 , carNum= 'null' , brand= '宝马' , guidePrice=null, produceTime= 'null' , carType= 'null' } Car{ id = 4 , carNum= 'null' , brand= '宝马' , guidePrice=null, produceTime= 'null' , carType= 'null' } Car{ id = 5 , carNum= 'null' , brand= '宝马' , guidePrice=null, produceTime= 'null' , carType= 'null' } ... 问题 : id 和 brand 正常映射,但 carNum 、 guidePrice 、 produceTime 、 carType 均为 null 。 这到底是为什么? 二、原因研判 2.1 根本原因:列名与属性名不匹配 观察表字段和 Java 属性的对应关系: 数据库列名(下划线) Java 属性名(驼峰) 是否一致 id id ✅ 一致 brand brand ✅ 一致 car_num carNum ❌ 不一致 guide_price guidePrice ❌ 不一致 produce_time produceTime ❌ 不一致 car_type carType ❌ 不一致 在 MyBatis 中,当使用 resultType 进行 自动映射 时,默认要求 数据库列名与 Java 属性名完全一致(大小写敏感) 。 对于 id 和 brand ,列名和属性名完全匹配 → ✅ 映射成功 对于 car_num 等字段,列名和属性名不匹配 → ❌ 映射失败,属性保持 null 这就是为什么部分字段能映射成功,而其他字段却为 null 的根本原因。 2.2 为什么没有报错? MyBatis 的自动映射是 宽容 的。对于无法匹配的列,它不会抛出异常,而是 忽略 该列的映射,Java 对象中的对应属性会保持默认值(引用类型为 null ,基本类型为默认值)。这就是为什么你能看到 carNum=null 、 guidePrice=null 的结果。 三、解决方案(三选一) 方案一:开启驼峰命名自动转换 ⭐ 推荐 MyBatis 提供了一个全局开关,可以将数据库的 下划线命名 自动映射为 Java 的 驼峰命名 。 在 mybatis-config.xml 中添加: < settings > < setting name = "mapUnderscoreToCamelCase" value = "true" /> 开启后,MyBatis 会自动完成以下映射: car_num → carNum guide_price → guidePrice produce_time → produceTime car_type → carType 优点 : 配置一次,全局生效。 所有 Mapper 都不需要额外修改。 代码简洁,维护成本最低。 适用场景 : 所有工程都推荐开启 ,这是 MyBatis 官方推荐的最佳实践之一。 方案二:使用 resultMap 手动映射 如果不想开启全局设置(例如项目中有特殊需求),可以使用 resultMap 手动指定列与属性的映射关系: < resultMap id = "carMap" type = "car" > < id property = "id" column = "id" /> < result property = "carNum" column = "car_num" /> < result property = "brand" column = "brand" /> < result property = "guidePrice" column = "guide_price" /> < result property = "produceTime" column = "produce_time" /> < result property = "carType" column = "car_type" /> < select id = "selectAll" resultMap = "carMap" > SELECT * FROM t_car 注意 :使用 resultMap 时,