MongoDB传入正确ID字符串调用findById仍返回not found求助
MongoDB按ID查询匹配却返回“未找到”的解决方案
问题描述
传入与数据库完全一致的ID字符串,调用Spring Data MongoDB的findById方法却抛出“Oferta especial not found”异常,相关代码及错误日志如下:
Controller代码
/** * 接收OfertaEspecial的ID,为每个Destinatario生成Voucher。 */ @PostMapping("{id}") public void generateVoucher(@PathVariable String id) { voucherService.generateVoucher(id); }
Service代码
public void generateVoucher(String id) { //通过ID获取OfertaEspecial,检查其是否存在于数据库中。若不存在则抛出异常。 OfertaEspecial ofertaEspecial = ofertaEspecialRepository.findById(id) .orElseThrow(() -> new RuntimeException("Oferta especial not found")); // .... }
错误日志
java.lang.RuntimeException: Oferta especial not found at com.launchersoft.vouchersapi.service.VoucherService.lambda$generateVoucher$0(VoucherService.java:39) ~[classes/:na] java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) ~\[na:na\] at java.base/java.lang.reflect.Method.invoke(Method.java:577) ~[na:na\]
解决步骤
1. 排查ID字符串的隐藏字符问题
肉眼一致的字符串可能包含空格、换行符等不可见字符,直接导致匹配失败。在Service方法中添加日志输出ID的详细信息:
public void generateVoucher(String id) { // 打印ID的长度与原始内容 System.out.println("传入ID长度:" + id.length()); System.out.println("传入ID原始内容:'" + id + "'"); OfertaEspecial ofertaEspecial = ofertaEspecialRepository.findById(id) .orElseThrow(() -> new RuntimeException("Oferta especial not found")); // .... }
若发现多余字符,对ID做清理处理:
id = id.trim(); // 去除前后空格
2. 检查实体类ID字段的注解与类型匹配
确保实体类ID字段使用Spring Data的@Id注解,且类型与数据库_id类型一致:
- 若数据库
_id为ObjectId类型,实体类ID可定义为String(Spring Data自动转换)或ObjectId:import org.springframework.data.annotation.Id; import org.bson.types.ObjectId; public class OfertaEspecial { @Id private ObjectId id; // 或 private String id; // 其他字段 } - 若数据库
_id为字符串类型,实体类ID必须定义为String。
3. 手动构造ObjectId查询
若数据库_id是ObjectId类型,尝试手动转换ID后查询(需同步修改仓库接口泛型):
修改仓库接口泛型
import org.springframework.data.mongodb.repository.MongoRepository; import org.bson.types.ObjectId; public interface OfertaEspecialRepository extends MongoRepository<OfertaEspecial, ObjectId> { }
修改Service查询逻辑
import org.bson.types.ObjectId; public void generateVoucher(String id) { if (!ObjectId.isValid(id)) { throw new RuntimeException("无效的Oferta especial ID"); } OfertaEspecial ofertaEspecial = ofertaEspecialRepository.findById(new ObjectId(id)) .orElseThrow(() -> new RuntimeException("Oferta especial not found")); // .... }
4. 使用MongoTemplate直接查询验证
若Spring Data Repository自动转换存在问题,用MongoTemplate构造原生查询验证:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.bson.types.ObjectId; @Autowired private MongoTemplate mongoTemplate; public void generateVoucher(String id) { OfertaEspecial ofertaEspecial; if (ObjectId.isValid(id)) { ofertaEspecial = mongoTemplate.findOne( Query.query(Criteria.where("_id").is(new ObjectId(id))), OfertaEspecial.class ); } else { ofertaEspecial = mongoTemplate.findOne( Query.query(Criteria.where("_id").is(id)), OfertaEspecial.class ); } if (ofertaEspecial == null) { throw new RuntimeException("Oferta especial not found"); } // .... }
5. 确认数据库连接与集合映射
检查应用连接的MongoDB实例、数据库是否正确,实体类集合名称与数据库一致(可通过@Document(collection = "oferta_especial")指定)。
内容的提问来源于stack exchange,提问作者Rômulo Sorato
相关产品推荐
相关产品推荐

