Spring Boot中PostMapping接收binary16字符串转UUID问题求助
Binary16字符串转UUID问题求助
我需要将请求中的binary16格式字符串转换为UUID,尝试了多种方法都没解决。场景是从MySQL数据库读取binary16类型的UUID数据,同时接口接收的JSON请求里也是这种无分隔符的32位字符串(比如5a61a32a5ab045dbb5a2bf25425da963)。我试过在DTO或实体类里用String类型接收,但还是无法正确转换为UUID存入数据库。
相关代码如下:
实体类代码
@NoArgsConstructor @ToString @Entity @Table(name = "attendant") public class AttendantModel implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) @Getter private UUID attendantID; @Column(nullable = false, length = 100) @Getter @Setter private String name; @Column @Getter @Setter private UUID productID1; @Column @Getter @Setter private UUID productID2; @Column @Getter @Setter private UUID instructionID; }
控制器代码
@RestController @RequestMapping("/api/attendant") public class AttendantController { final AttendantService attendantService; public AttendantController(AttendantService attendantService) { this.attendantService = attendantService; } @Autowired private AttendantRepository attendantRepository; @PostMapping public ResponseEntity<Object> saveInstructions(@RequestBody @Valid AttendantDto attendantDto) { var attendantModel = new AttendantModel(); BeanUtils.copyProperties(attendantDto, attendantModel); return ResponseEntity.status(HttpStatus.CREATED).body(attendantService.save(attendantModel)); } }
DTO类代码
public class AttendantDto { @NotBlank @Size(max = 100) @Getter @Setter private String name; @Getter @Setter private UUID productID1; @Getter @Setter private UUID productID2; @Getter @Setter private UUID instructionID; }
JSON请求示例
{ "name": "Júlia - vendedora", "productID1": "5a61a32a5ab045dbb5a2bf25425da963" }
解决方案
方法1:自定义JSON转换器(适配无分隔符UUID字符串)
Spring默认的UUID转换器只识别带-分隔符的标准UUID格式,你需要自定义转换器处理无分隔符的32位字符串:
- 编写自定义反序列化器:
public class CustomUuidDeserializer extends StdDeserializer<UUID> { protected CustomUuidDeserializer() { super(UUID.class); } @Override public UUID deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { String uuidStr = p.getText().trim(); // 给无分隔符字符串插入分隔符,转为标准UUID格式 if (uuidStr.length() == 32) { String formatted = String.format("%s-%s-%s-%s-%s", uuidStr.substring(0, 8), uuidStr.substring(8, 12), uuidStr.substring(12, 16), uuidStr.substring(16, 20), uuidStr.substring(20)); return UUID.fromString(formatted); } // 兼容标准格式UUID return UUID.fromString(uuidStr); } }
- 在DTO的UUID字段上指定该反序列化器:
@Getter @Setter @JsonDeserialize(using = CustomUuidDeserializer.class) private UUID productID1; @Getter @Setter @JsonDeserialize(using = CustomUuidDeserializer.class) private UUID productID2; @Getter @Setter @JsonDeserialize(using = CustomUuidDeserializer.class) private UUID instructionID;
方法2:DTO用String接收,手动转换为UUID
如果不想自定义转换器,可以在DTO中用String接收字段,转换实体类时手动处理格式:
- 修改DTO字段类型:
@Getter @Setter private String productID1; @Getter @Setter private String productID2; @Getter @Setter private String instructionID;
- 在控制器中手动转换:
@PostMapping public ResponseEntity<Object> saveInstructions(@RequestBody @Valid AttendantDto attendantDto) { var attendantModel = new AttendantModel(); BeanUtils.copyProperties(attendantDto, attendantModel); // 转换productID1 if (attendantDto.getProductID1() != null && !attendantDto.getProductID1().isEmpty()) { String pid1 = attendantDto.getProductID1(); String formattedPid1 = String.format("%s-%s-%s-%s-%s", pid1.substring(0,8), pid1.substring(8,12), pid1.substring(12,16), pid1.substring(16,20), pid1.substring(20)); attendantModel.setProductID1(UUID.fromString(formattedPid1)); } // 同理处理productID2和instructionID return ResponseEntity.status(HttpStatus.CREATED).body(attendantService.save(attendantModel)); }
方法3:配置JPA适配MySQL的binary16存储
确保MySQL中对应字段为BINARY(16)类型,JPA会自动处理UUID与binary16的转换。若字段类型不符,先修改表结构:
ALTER TABLE attendant MODIFY COLUMN productID1 BINARY(16); ALTER TABLE attendant MODIFY COLUMN productID2 BINARY(16); ALTER TABLE attendant MODIFY COLUMN instructionID BINARY(16);
同时在实体类的UUID字段上明确指定列类型,避免JPA自动生成错误类型:
@Column(columnDefinition = "BINARY(16)") @Getter @Setter private UUID productID1;
内容的提问来源于stack exchange,提问作者Antonio Souza
相关产品推荐
相关产品推荐

