Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde...

现象

现在有这么个类需要插入到 MongoDB 中:

@Data
@Document(collection = "biz_order")
public class BizOrder {

    @Field
    private String id;

    @Field
    // 其他属性

}

有个操作是根据 BizOrder 的某个字段不同,会往 MongoDB 中插入多条数据,即其他属性都是一样的,只有一个字段不一样。

我的操作是这样的:

BizOrder bizOrder = new BizOrder();
for(int i=0; i<3; i++) {
    bizOrder.setStatus(i);
    bizOrderDao.insert(bizOrder);
}

 

然后就会抛异常,由于这个多次插入的概率比较小,一般都是插入一次,所以就没有注意到抛出的异常:

Spring data mongo E11000 duplicate key error collection: index: _id_ dup

后来查询相关资料,发现是 MongoDB 自动生成的 ID 惹的祸。

问题追踪

MongoDB 中的一条记录一般称之为 文档(Document),每个 Document 都有唯一的一个 id,如果你不指定的话,MongoDB 会自动给你生成一条。

现在我们用的 Spring Data MongoDB Template,来看一下源码的 insert 操作是如何进行的。

MongoTemplate API 的 insert 方法:

Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde..._第1张图片

平平无奇,继续往下看:

Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde..._第2张图片

还是平平无奇,看到了 doInsert 方法就知道了,真正的插入操作在这里完成的:

Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde..._第3张图片

最后来看一下 populateIdIfNecessary 这个方法:

Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde..._第4张图片

 

 Spring Data MongoTemplate insert 操作的大坑:Spring data mongo E11000 duplicate key error collection: inde..._第5张图片

所以,当 BizOrder 插入时候的 id 为空的时候,Spring Data Mongo Template 会把 MongoDB 自动生成的 id,赋值到 BizOrder 中。

如果这个时候,你仍然使用这个 BizOrder 对象去插入,那么,MongoDB 会先检查 BizOrder 的 id,结果发现库里已经有了这个 id,所以会抛出重复 id 主键的异常。

结论

解决办法是:用新的对象去插入,或者把 id 的属性置为 null。

妈蛋,坑真多,一旦用了一个新玩意儿,要小心仔细,尽量各个角落都要注意到;慢查询和数据库操作层面的异常都要注意到。

转载于:https://www.cnblogs.com/tuhooo/p/11277296.html

你可能感兴趣的:(java,数据库)