Spring中如何将自动生成的@Id主键限制为6位长度
Spring 自定义6位长度@Id主键实现方案
你当前遇到的问题本质是使用了Spring Data MongoDB的默认主键生成策略:String类型的@Id字段默认会自动生成24位长度的ObjectId字符串,要改成6位长度的主键,核心是替换默认的主键生成逻辑,全程不需要改动你现有控制器的业务代码。
实现步骤
1. 编写自定义6位主键生成逻辑
直接实现Spring Data MongoDB的BeforeConvertCallback接口,在实体类被存储到MongoDB之前统一拦截赋值,同时做唯一性校验避免主键冲突:
public class SixDigitIdGenerator implements BeforeConvertCallback<Object, String> { // 字符池去掉易混淆的0、1、I、O,避免用户识别误差 private static final String ID_CHAR_POOL = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; private static final int ID_LENGTH = 6; private final MongoTemplate mongoTemplate; public SixDigitIdGenerator(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } @Override public Object onBeforeConvert(Object entity, String collectionName) { // 仅对没有手动赋值id的实体做自动生成 Field idField = ReflectionUtils.findField(entity.getClass(), "id"); ReflectionUtils.makeAccessible(idField); Object existingId = ReflectionUtils.getField(idField, entity); if (existingId != null && StringUtils.hasText(existingId.toString())) { return entity; } // 循环生成不重复的6位id String generatedId; do { generatedId = RandomStringUtils.random(ID_LENGTH, ID_CHAR_POOL); Query checkQuery = Query.query(Criteria.where("_id").is(generatedId)); if (!mongoTemplate.exists(checkQuery, collectionName)) { break; } } while (true); ReflectionUtils.setField(idField, entity, generatedId); return entity; } }
2. 注册生成器为Spring Bean
在项目的Spring配置类中注册上面写的生成器,让Spring Data MongoDB自动加载生效:
@Configuration public class MongoConfig { @Bean public SixDigitIdGenerator sixDigitIdGenerator(MongoTemplate mongoTemplate) { return new SixDigitIdGenerator(mongoTemplate); } }
3. 现有代码无需改动
- 实体类保持原有
@Id private String id;的定义即可,不需要调整注解结构 - 控制器里的逻辑完全兼容:执行
repository.save(model)时,框架会自动触发自定义生成逻辑,给id字段赋值6位长度的字符串,后续通过model.getId()拿到的就是符合长度要求的主键。
关键说明
- 6位字符(32个可选字符)的总可用id量超过10亿,配合生成时的重复校验,完全可以覆盖常规业务的请求记录存储需求,主键冲突概率极低
- 不要在控制器save前手动随机生成id再赋值,这种写法很容易漏掉重复校验,把生成逻辑放在Mongo存储拦截层,所有save入口都会统一执行校验,不会出现漏判主键冲突的问题
- 自定义生成器会完全替代默认的24位ObjectId生成逻辑,不需要调整MongoDB原有集合的存储结构,对存量数据没有影响
内容的提问来源于stack exchange,提问作者Bhavya
相关产品推荐
相关产品推荐

