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

Spring Boot MongoDB复合主键查询无数据返回的问题解决

问题描述

定义了如下结构的ProductId复合主键类、Product实体类,以及继承MongoRepository的ProductRepository:

@Data
class ProductId{
    Long productId;
    Long categoryCode;
}
      
@Data
@Document(collection = "products")
class Product {
            
    @Id
    ProductId id; 
           
    Long productName;
    Long category;
    Long quantityInStock;
            
    @PersistenceCreator
    Product(ProductId id,Long productName,Long category,Long quantityInStock){
        this.id = id;
        this.productName= productName;
        this.category = category;
        this.quantityInStock = quantityInStock;
    }
}         
public interface ProductRepository extends MongoRepository<Product, ProductId> {
   
}

调用productRepository.findById(id)返回Optional.empty,使用以下批量查询代码也返回空列表:

public List<Product> find(List<ProductId> ids) {                 
    Query query = new Query();
    Criteria criteria = Criteria.where("id").in(ids);
    query.addCriteria(criteria);
    List<Product> results = mongoTemplate.find(query, Product.class);
    return results;
}

但Studio 3T中存在对应数据:

{
    "_id": {
         "productId": 872223334,
         "categoryCode": 4
    },
    "productName": "Decantor Jacket",
    "category": "Plaid-Item",
    "quantityInStock": 4001
}
修复方案

1. 修正实体类字段类型不匹配

数据库中productName和category是字符串类型,但代码里错误定义为Long,类型不匹配会导致映射失败,直接修改字段类型:

@Data
@Document(collection = "products")
class Product {
    
    @Id
    ProductId id; 
    
    String productName; // 改为String类型
    String category; // 改为String类型
    Long quantityInStock;
    
    @PersistenceCreator
    Product(ProductId id, String productName, String category, Long quantityInStock){
        this.id = id;
        this.productName = productName;
        this.category = category;
        this.quantityInStock = quantityInStock;
    }
}

2. 让复合主键类实现Serializable接口

Spring Data MongoDB要求主键类必须实现Serializable接口,否则无法正确处理主键的序列化与反序列化:

@Data
class ProductId implements Serializable {
    private static final long serialVersionUID = 1L; // 添加序列化版本号
    Long productId;
    Long categoryCode;
}

3. 修正批量查询的主键字段名

MongoDB中主键存储在_id字段下,而非代码里的id,需要修改查询条件的字段名:

public List<Product> find(List<ProductId> ids) {                 
    Query query = new Query();
    Criteria criteria = Criteria.where("_id").in(ids); // 将"id"改为"_id"
    query.addCriteria(criteria);
    List<Product> results = mongoTemplate.find(query, Product.class);
    return results;
}

4. 确保主键对象属性匹配

查询时传入的ProductId对象,其productId和categoryCode的值要与数据库中_id下的对应字段完全一致(包括数据类型,比如都为Long类型)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:53:13