You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中如何防止POJO类字段存入MongoDB时出现重复值

解决方案

原代码问题分析

  • 未查询数据库校验重复:判断重复的逻辑基于本地新建的ArrayList,仅包含当前传入的itemName,永远不会命中重复判断,完全没有查询MongoDB中已存在的记录
  • 数据存储逻辑错误:调用mongoTemplate.save()时传入的是List对象而非Items实体对象,存储对象类型不符合预期
  • 循环逻辑完全冗余:创建的集合只有1个元素,循环遍历没有任何实际作用

修复步骤

步骤1:为itemName字段添加唯一索引(数据库层兜底防重)

这一步是最可靠的防重手段,即使应用层校验出现并发漏判,数据库也会直接拒绝重复写入。

首先修改POJO类,给itemName加唯一索引注解:

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "items") // 显式指定集合名,可选但推荐
public class Items {
    @Id
    private String id;
    @Indexed(unique = true) // 新增唯一索引注解
    private String itemName;

    // 此处省略getter、setter方法
}

然后开启Spring Data MongoDB的自动索引创建,在application.yml/application.properties添加配置:

spring.data.mongodb.auto-index-creation=true

如果不想开启自动索引创建,也可以手动调用接口创建索引,项目启动时执行一次即可:

mongoTemplate.indexOps(Items.class).ensureIndex(new Index("itemName", Sort.Direction.ASC).unique());

步骤2:修复业务层写入逻辑

先查询数据库是否存在相同itemName的记录,存在则直接抛出指定错误,不存在再执行插入,同时捕获唯一索引冲突异常处理并发场景:

import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;

public void addCategory(Items item) {
    // 1. 先查询数据库判断是否已存在相同itemName
    boolean exists = mongoTemplate.exists(
        Query.query(Criteria.where("itemName").is(item.getItemName())),
        Items.class
    );
    if (exists) {
        throw new IllegalArgumentException("item already exists");
    }
    try {
        // 2. 不存在则执行插入
        mongoTemplate.save(item);
    } catch (DuplicateKeyException e) {
        // 并发请求场景下,两个请求同时通过前面的exists校验时,会触发数据库唯一索引冲突,统一转成指定错误
        throw new IllegalArgumentException("item already exists");
    }
}

内容的提问来源于stack exchange,提问作者Sahith Manchi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 20:21:00