使用Spring Boot基于组织ID生成从1开始的顺序子ID的简便方法是什么?
分层业务ID生成实现思路与落地方案
核心设计逻辑
原来的全局序列生成器是单维度计数,现在只需要把计数维度改成组织ID + 业务对象类型的复合维度,每个复合维度对应独立的计数序列即可,完全适配你要的每个组织下同类型业务对象从1开始递增的要求。
可直接落地的实现方案
方案1:数据库维护序列表(兼容性最高,无额外依赖)
- 新建一张序列维护表
biz_sequence_config,字段设计如下:CREATE TABLE biz_sequence_config ( id BIGINT PRIMARY KEY AUTO_INCREMENT, org_id VARCHAR(32) NOT NULL COMMENT '所属组织ID,比如ORG0001', biz_type VARCHAR(32) NOT NULL COMMENT '业务类型,比如USR/VEH', current_seq INT NOT NULL DEFAULT 0 COMMENT '当前已使用的序列值', UNIQUE KEY uk_org_biz (org_id, biz_type) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - 新增业务对象时的ID生成逻辑:
- 先获取该对象关联的组织ID、对应业务类型
- 对
biz_sequence_config表对应org_id + biz_type的行执行行锁更新,将current_seq自增1,返回更新后的序列值 - 把返回的序列值按你原来的规则补零拼接前缀,比如序列值1、业务类型USR就拼接成
USR0001
- 注意点:更新操作要加行锁避免并发冲突,用
SELECT ... FOR UPDATE或者直接执行UPDATE biz_sequence_config SET current_seq = current_seq +1 WHERE org_id = ? AND biz_type = ?然后查询最新值即可,高并发场景可以加一段步长缓存,比如一次拿10个序列存在内存里用完再取,降低数据库压力。
方案2:基于Hibernate自定义ID生成器(适配原有SequenceStyleGenerator使用习惯)
如果你原来的ID生成是通过Hibernate注解注入的,可以直接自定义一个继承SequenceStyleGenerator的生成器,重写generate方法:
- 重写逻辑里先从待保存的实体对象中取出关联的
orgId字段值、以及当前实体对应的业务类型前缀 - 按
orgId + 业务类型拼接成唯一的序列名称,调用父类的生成逻辑时动态传入这个序列名称即可,Hibernate会自动为每个不同的序列名称维护独立的计数。 - 实体类注解示例:
@Id @GeneratedValue(generator = "org_biz_seq_generator") @GenericGenerator( name = "org_biz_seq_generator", strategy = "com.xxx.CustomOrgBizSequenceGenerator", parameters = { @Parameter(name = "prefix", value = "USR"), @Parameter(name = "number_format", value = "%04d") } ) private String userId;
边缘场景处理
- 新增组织时可以提前为该组织下所有业务类型初始化序列行,
current_seq设为0即可,也可以第一次生成对应类型ID的时候自动初始化,避免查不到行的问题 - 如果要做分布式部署,方案1直接用数据库行锁天然支持分布式,方案2如果用Hibernate的数据库序列实现的话也天然支持分布式,不需要额外调整
内容的提问来源于stack exchange,提问作者Nipuna Perera
相关产品推荐
相关产品推荐

