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
相关产品推荐
相关产品推荐

