SpringBoot REST API是否应返回主键?替代方案及最佳实践咨询
REST API医生标识方案问题解答
你当前使用Spring Boot构建的REST接口如下:
@GetMapping("/v1/search/symptom/{symptom}") public List<DoctorDTO> getDoctorsForSymptom(@PathVariable("symptom") String symptomQuery){ List<DoctorDTO> doctorDTOList = this.symptomService.getDoctorsForSymptom(symptomQuery); //we can add code here for caching the result to make response faster return doctorDTOList; }
对应的Doctor实体定义:
public class Doctor { private long doctorId; private String name; private int age; private String mobileNum; private MedicalSpeciality medicalSpeciality; private List<Slot> slots; private List<DoctorSymptomAssociation> doctorSymtomAssociations; }
针对你提出的问题,解答如下:
一、不返回主键时如何识别同一医生
- 使用业务唯一标识:如果
mobileNum(手机号)在系统中是唯一且不可变更的,可以用它作为后续请求的标识。注意手机号属于敏感信息,传输和存储需加密处理。 - 临时令牌映射:返回DoctorDTO时生成带过期时间的临时令牌(如JWT),令牌内嵌医生主键信息。后续请求携带令牌,后端验证后提取主键操作。这种方式避免主键直接暴露,同时保证安全性,但需维护令牌生命周期。
- 自定义业务编码:为每个医生生成唯一的业务编码(如
DOC-2024-0015),编码与主键在数据库关联,返回编码给前端作为标识。编码可设计为无规律但易识别的格式,既规避主键递增特性暴露,又满足业务识别需求。
二、新增UUID字段替代主键返回是否可行
完全可行。你可以在Doctor实体中新增uuid字段(MySQL中用CHAR(36)类型存储),医生创建时自动生成UUID并持久化,接口返回该UUID代替自增主键。
UUID的弊端:
- 存储占用大:自增bigint是8字节,UUID字符串是36字节,增加存储成本。
- 索引性能差:UUID无序,插入时会导致索引页频繁分裂,降低写入性能。
- 可读性弱:不利于日志排查和人工识别。
三、适配MySQL的更优方案
1. 雪花算法生成ID
雪花算法生成64位长整型全局唯一ID,包含时间戳、机器标识、序列号,具备递增特性。相比UUID:
- 存储占用与自增主键一致(8字节),节省空间。
- 递增特性避免索引页分裂,写入性能更优。
- 可读性优于UUID,且不暴露业务数据。
实现时可新增snowflakeId字段,创建医生时生成并存储,接口返回该ID。
2. MySQL原生短UUID
利用MySQL的UUID_SHORT()函数生成64位整数型短UUID,作为医生的唯一标识字段。该ID是全局唯一的整数,存储和索引性能与自增主键一致,同时避免了自增主键的暴露风险。
3. 缓存映射临时标识
若不想新增数据库字段,可在返回DTO时生成随机字符串作为临时标识,将标识与医生主键存入Redis并设置过期时间。后续请求携带临时标识,后端从Redis中取出主键进行操作。此方式无需修改数据库,但需维护缓存的过期策略,防止内存溢出。
内容的提问来源于stack exchange,提问作者Mayank Kumar Thakur
相关产品推荐
相关产品推荐

