Spring Boot集成MongoDB时UUID格式ID验证失败问题解决
问题:Spring Boot集成MongoDB通过ID查询时触发UUID验证错误
在Spring Boot集成MongoDB的示例项目中,通过ID查询实体时触发验证错误,抛出提示“must be a valid UUID”。
实体类代码
@Getter @Setter @SuperBuilder @EqualsAndHashCode(callSuper = true) @NoArgsConstructor @AllArgsConstructor @Document(collection = "airport-collection") public class AirportEntity extends BaseEntity { @Id @Indexed(unique = true) @Field(name = "_id") private String id = UUID.randomUUID().toString(); @Field(name = "AIRPORT_NAME") private String name; @Field(name = "CITY_NAME") private String cityName; }
请求与错误响应
通过Controller的getAirportById(@PathVariable @Valid @UUID final String id)方法请求localhost:8080/api/v1/airports/6781972fa25a3e577395c444时,得到错误响应:
{ "time": "2025-01-11T00:55:27.5670908", "httpStatus": "BAD_REQUEST", "header": "VALIDATION ERROR", "message": "Constraint violation", "isSuccess": false, "subErrors": [ { "message": "must be a valid UUID", "field": "id", "value": "6781972fa25a3e577395c444", "type": "String" } ] }
数据库存储的ID
_id : ObjectId(6781972fa25a3e577395c444) AIRPORT_NAME : String CITY_NAME : String _class : Entity class
解决方案
1. 移除Controller参数的@UUID验证注解
数据库中存储的_id是MongoDB自动生成的ObjectId(24位十六进制字符串),并非标准UUID格式(带连字符的36位字符串)。你在Controller方法参数上添加的@UUID验证注解会拦截不符合格式的请求,直接移除该注解即可:
// 修改后的Controller方法 public ResponseEntity<AirportEntity> getAirportById(@PathVariable @Valid final String id) { // 查询逻辑 }
2. 统一使用UUID作为ID(若业务需要)
如果希望保持UUID作为实体ID,需调整实体类和数据存储逻辑:
- 修改实体类,直接使用UUID类型存储ID:
或保持String类型,但确保生成的是带连字符的标准UUID字符串,同时插入数据时禁止MongoDB自动生成ObjectId。@Id @Indexed(unique = true) @Field(name = "_id") private UUID id = UUID.randomUUID();
3. 适配MongoDB的ObjectId类型
如果要使用MongoDB原生的ObjectId作为ID,可修改实体类的ID字段类型:
import org.bson.types.ObjectId; @Id @Indexed(unique = true) @Field(name = "_id") private ObjectId id;
同时Controller方法参数可改为ObjectId类型,或保持String类型并在查询时转换为ObjectId:
// Controller方法示例 public ResponseEntity<AirportEntity> getAirportById(@PathVariable @Valid final String id) { ObjectId objectId = new ObjectId(id); AirportEntity airport = airportRepository.findById(objectId).orElseThrow(...); return ResponseEntity.ok(airport); }
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

