ReactiveMongoTemplate查询不存在元素时map方法未执行求助
问题原因分析
你的代码里map没有执行,核心问题出在对MongoTemplate.findOne()返回值的理解和Optional(如果用的是新版本Spring Data)的用法上:
返回值类型的坑:
- 在Spring Data MongoDB 2.0及以上版本中,
findOne()方法返回的是Optional<DeviceSettings>,而不是直接返回DeviceSettings对象(旧版本可能返回null)。 - 当查询不到文档时,它返回的是
Optional.empty(),而不是null。Optional的map()方法只会在容器内有非空值的时候才会执行映射逻辑,空Optional调用map()会直接返回空Optional,根本不会进入你写的lambda表达式,所以你写的null -> defaultSettings(clock)分支完全没有机会被触发。
- 在Spring Data MongoDB 2.0及以上版本中,
逻辑冗余且错误:
就算是旧版本返回null的情况,你直接对null调用map()会抛出NullPointerException,根本执行不到你内部的when判断;而如果是Optional的情况,map里的it永远不会是null,所以你的null分支完全是多余的。
解决办法
根据你使用的Spring Data版本,分两种情况处理:
情况1:使用Spring Data MongoDB 2.0+(返回Optional)
直接用map处理有值的情况,再用orElseGet提供默认值,这是最符合Optional设计的写法:
return template.findOne(Query().addCriteria(Criteria.where("id")), DeviceSettings::class.java) .map { listOf( Instant.now(clock).toString(), it.nextMeasurement.toString(), it.shouldUpdateFirmware.toString() ) } .orElseGet { defaultSettings(clock) }
map:当查询到文档时,将DeviceSettings转换为你需要的列表orElseGet:当查询不到文档(Optional为空)时,执行默认值逻辑并返回
情况2:使用旧版本Spring Data MongoDB(返回可能为null的DeviceSettings)
先把返回值包装成Optional,再用同样的逻辑处理,避免NullPointerException:
return Optional.ofNullable(template.findOne(Query().addCriteria(Criteria.where("id")), DeviceSettings::class.java)) .map { listOf( Instant.now(clock).toString(), it.nextMeasurement.toString(), it.shouldUpdateFirmware.toString() ) } .orElseGet { defaultSettings(clock) }
额外提示
- 尽量避免在
Optional.map()里做null判断,因为Optional本身就是用来处理null安全的,它的设计就是保证map里的参数永远是非空的。 - 如果你的
defaultSettings(clock)返回的类型和map转换后的类型一致(都是List<String>),上面的写法就能完美工作。
内容的提问来源于stack exchange,提问作者pixel
相关产品推荐
相关产品推荐

