SpringBoot整合MongoDB时save后DBRef关联字段返回null如何解决
问题根因
Spring Data MongoDB的MongoRepository.save()方法不会自动解析待保存对象中标记@DBRef的关联实体。你传入的请求体里Bar.baz仅携带了id属性,没有其他字段值,save方法完成持久化后直接返回内存中原来的入参对象,不会主动查询关联的Baz文档做属性填充,因此返回结果里baz_name为null。而调用GET接口查询数据时,框架会自动解析所有@DBRef标记的关联,从对应集合查出完整文档填充属性,因此能拿到正确的baz_name值。
方案1:保存后直接返回完整关联数据
两种实现方式可选:
- 写法1(改动最小,推荐):保存后按id重新查询一次再返回
直接修改POST接口逻辑,save完成后不直接返回入参对象,而是用save返回的实体id重新从repository查询,框架会自动解析所有@DBRef关联,填充完整属性:@PostMapping public Foo addFoo(@RequestBody Foo foo) { Foo persisted = repository.save(foo); // 重新查询会自动解析所有DBRef关联,填充完整字段 return repository.findById(persisted.getId()).orElseThrow(); } - 写法2(减少一次全量查询):保存前主动填充关联对象
如果不想额外做一次Foo的全量查询,可以在save前手动把所有关联的Baz查出来填充到对象里,再保存返回:// 提前注入Baz对应的Repository @Autowired private BazRepository bazRepository; @PostMapping public Foo addFoo(@RequestBody Foo foo) { // 收集所有关联Baz的id Set<String> bazIds = foo.getBars().stream() .map(bar -> bar.getBaz().getId()) .collect(Collectors.toSet()); // 批量查询所有关联的Baz Map<String, Baz> bazRefMap = bazRepository.findAllById(bazIds).stream() .collect(Collectors.toMap(Baz::getId, Function.identity())); // 替换Bar中仅带id的Baz为完整查询结果 foo.getBars().forEach(bar -> bar.setBaz(bazRefMap.get(bar.getBaz().getId()))); // 此时对象内关联字段已填充完整,直接保存返回即可 return repository.save(foo); }
方案2:兜底方案,不返回不符合实际存储的null值
如果不想额外增加查询逻辑,只需要避免返回和实际存储不符的null字段,可以通过Jackson序列化配置,让null值不输出到响应结果中:
- 全局配置:所有接口返回的实体都自动忽略null值
在application.yml中添加如下配置:spring: jackson: default-property-inclusion: non_null - 单类配置:仅让Baz类的null字段不返回,不影响其他实体
直接在Baz类上添加Jackson注解:
配置完成后,POST接口返回结果中不会出现@Document(collection = "bazs") @JsonInclude(JsonInclude.Include.NON_NULL) public class Baz { @Id private String id; private String baz_name; }baz_name: null字段,仅返回实际存在的id字段,不会出现和数据库存储不符的null值。
内容的提问来源于stack exchange,提问作者Rauññ
相关产品推荐
相关产品推荐

