MongoDB执行upsert时因修改_id字段报错的问题求助
解决MongoDB Upsert时
_id字段不可修改的报错问题 这个报错的核心原因很明确:MongoDB的_id字段是文档的主键,一旦创建就不允许修改,而你的代码和实体类映射出现了冲突。
问题根源分析
在Spring Data MongoDB中,实体类里的id字段默认会自动映射到MongoDB文档的_id字段。你在代码中执行了update.set("id", String.valueOf(partnerId)),这相当于试图修改文档的_id值,直接触发了MongoDB的主键不可修改限制,所以抛出了错误。
两种可行的解决方案
方案一:让partnerId作为文档的主键(推荐)
既然你是用partnerId作为upsert的匹配条件,完全可以把partnerId设为MongoDB文档的_id,这样既符合业务逻辑,又避免了额外的id字段冲突。
修改你的PartnerAppIds实体类:
public class PartnerAppIds { @Id // 指定该字段为MongoDB文档的_id主键 private Long partnerId; @Indexed private Set<String> appIds; public Long getPartnerId() { return partnerId; } public void setPartnerId(Long partnerId) { this.partnerId = partnerId; } public Set<String> getAppIds() { return appIds; } public void setAppIds(Set<String> appIds) { this.appIds = appIds; } }
然后简化你的upsert代码,去掉修改id的操作:
final Update update = new Update(); update.pushAll("appIds", appIds.toArray()); mongoTemplate.upsert(Query.query(Criteria.where("partnerId").is(partnerId)), update, PartnerAppIds.class);
方案二:保留原实体结构,但禁止在Update中修改id
如果你需要保留id字段(比如它有其他业务用途),只需要删除代码中修改id的那一行即可:
final Update update = new Update(); // 删掉这一行:update.set("id", String.valueOf(partnerId)); update.pushAll("appIds", appIds.toArray()); mongoTemplate.upsert(Query.query(Criteria.where("partnerId").is(partnerId)), update, PartnerAppIds.class);
注意:如果是执行upsert中的插入操作(文档不存在时),Spring Data MongoDB会自动为
id字段生成唯一值,你也可以在插入前手动给实体设置id值,但绝对不能在Update操作中修改它。
关键提示
MongoDB的_id字段是文档的唯一标识,具有不可变性,这是MongoDB的核心规则。在使用Spring Data MongoDB时,一定要注意实体类字段和_id的映射关系,避免出现类似的修改主键操作。
内容的提问来源于stack exchange,提问作者user3742525
相关产品推荐
相关产品推荐

