Spring Boot 3.0.5中ReactiveMongoTemplate更新抛出DuplicateKeyException
解决Spring Boot 3.0.5中MongoDB更新Post时的重复键异常
问题根源
你在Post类的comments字段上使用了@DocumentReference注解,这个注解用于建立MongoDB文档间的引用关系(类似关系型数据库的外键),该字段应存储Comment文档的_id值,而非完整的Comment实体。但你在addComment方法中,直接将插入后的完整Comment对象push到comments数组中,导致MongoDB尝试把包含自身_id的Comment对象存入Post的comments数组。后续操作时,Spring Data MongoDB会误将这个内嵌的Comment识别为需要独立保存的新实体,从而触发重复键错误(该Comment的_id已存在于comments集合中)。
修正方案
不需要让Post类实现Persistable接口,只需修改addComment方法,仅将Comment的id推送到Post的comments数组中:
@Override public Mono<Boolean> addComment(String id, String content) { return mongoTemplate.insert(Comment.builder().content(content).build()) .flatMap(c -> mongoTemplate.update(Post.class) .matching(where("id").is(id)) .apply(new Update().push("comments").value(c.getId())) .first() .hasElement() ); }
额外说明
如果你的业务需求是将Comment作为内嵌文档直接存储在Post的comments数组中(而非文档引用),直接移除comments字段上的@DocumentReference注解即可。此时完整的Comment对象会内嵌到Post文档里,不会出现引用相关的重复键问题。两种存储模式的选择取决于业务场景:
- 文档引用:适合
Comment需要被多个Post共享,或需要独立查询、更新Comment的场景 - 内嵌文档:适合
Comment仅属于某个Post,不需要独立操作的场景
内容的提问来源于stack exchange,提问作者Hantsy
相关产品推荐
相关产品推荐

