SpringBoot MongoTemplate查询MongoDB返回全null如何解决
问题根因
故障和BSON转JSON环节无关,是MongoDB文档到Java实体的映射逻辑存在两个核心问题:
- 字段名无映射匹配:MongoDB存储的字段为下划线命名(
emp_cd/leave_type/leave_start/leave_end),但Leave实体定义的是驼峰命名字段(employeeCode/leaveType/startDate/endDate),既没有配置全局驼峰转下划线的命名策略,也没有通过注解指定字段绑定关系,MongoTemplate读取到BSON字段后找不到Java实体中对应的属性,无法完成赋值。 - 实例化与类型转换缺失:你在配置类中手动实例化
MongoTemplate时,跳过了Spring Data MongoDB自带的转换器注册逻辑,既没有适配Java 17 Record类的全参构造实例化规则,也没有注册LocalDate类型和MongoDBISODate类型的双向转换器,日期字段无法正常解析,Record类也无法通过默认反射机制完成对象填充。
原生读取Document能拿到值,已经排除了数据查询环节的问题,故障完全出在ORM映射阶段。
解决方案
按以下步骤修改即可修复:
修正Leave实体,添加字段映射注解
给Record的每个字段添加@Field注解,明确指定和MongoDB字段的绑定关系:import org.springframework.data.mongodb.core.mapping.Field; import java.time.LocalDate; public record Leave( @Field("emp_cd") String employeeCode, @Field("leave_type") String leaveType, @Field("leave_start") LocalDate startDate, @Field("leave_end") LocalDate endDate ) {}如果使用的Spring Boot 2.7小版本低于2.7.12,建议先升级到2.7.12+,避免低版本对Java Record的映射兼容问题;也可以临时把Record改成普通类,添加
@Data、无参/全参构造注解验证逻辑。修正Mongo配置类,补全转换器与映射上下文
不要直接手动实例化裸的MongoTemplate,注册必要的日期转换器,确保映射逻辑正常加载:import org.springframework.boot.autoconfigure.AutoConfigureOrder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.Ordered; import org.springframework.core.convert.converter.Converter; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import java.time.LocalDate; import java.time.ZoneId; import java.util.Arrays; import java.util.Date; @Configuration @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE) public class ErpConfig { @Bean public MongoClient mongoClient() { return MongoClients.create("mongodb://localhost:27017"); } @Bean public MongoCustomConversions mongoCustomConversions() { return new MongoCustomConversions(Arrays.asList( // LocalDate 转 MongoDB ISODate (Converter<LocalDate, Date>) source -> Date.from(source.atStartOfDay(ZoneId.systemDefault()).toInstant()), // MongoDB ISODate 转 LocalDate (Converter<Date, LocalDate>) source -> source.toInstant().atZone(ZoneId.systemDefault()).toLocalDate() )); } @Bean public MongoTemplate mongoTemplate(MongoDatabaseFactory factory, MappingMongoConverter converter) { // 去除写入Mongo时自动生成的_class字段 converter.setTypeMapper(new DefaultMongoTypeMapper(null)); return new MongoTemplate(factory, converter); } }(可选)配置全局命名策略省略@Field注解
如果不想给每个实体字段加@Field指定下划线名称,可以在配置中添加全局驼峰转下划线的命名规则,自动完成Java驼峰字段和Mongo下划线字段的映射:@Bean public MongoMappingContext mongoMappingContext(MongoCustomConversions conversions) { MongoMappingContext context = new MongoMappingContext(); // 全局驼峰转下划线 context.setFieldNamingStrategy(property -> { char[] nameChars = property.getName().toCharArray(); StringBuilder fieldName = new StringBuilder(); for (char c : nameChars) { if (Character.isUpperCase(c)) { fieldName.append('_').append(Character.toLowerCase(c)); } else { fieldName.append(c); } } return fieldName.toString(); }); context.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); return context; }
修改完成后重启服务,再次发起Postman请求即可正常返回带值的业务数据。
内容的提问来源于stack exchange,提问作者Deep
相关产品推荐
相关产品推荐

