一、目标
实现自定义多级编码,且尽可能避免并发造成编码重复,以指标编码管理为例
二、开发环境
- 数据库:mysql8.x
三、实现原理
利用数据库事务的特性中的原子性:同一个事务中,要么全成功,要全失败。上图中编码生成过程和业务操作在同一事务中,所以当我们在生产新的编码过程中,编码次数记录表 属于锁定状态【具体是行锁还是表锁,视情况而定】,其他请求必须在本次事务提交后才能产生新的编码。由此,可以避免编码重复
三、效果呈现
指标模板编码: 00 00 000 0000
前两位:2位,业务域编码
3~4位:2位,业务域下主题编码
5~7位: 3位,主题下原子指标编码
8~11位:4位,原子指标派生的指标模板
- 业务域(一级)
- 主题(二级)
- 原子指标(三级)
- 业务指标(四级)
四、代码实现
- 初始化数据库
-- pub_code_max 最大编码次数记录
CREATE table pub_code_max (
id int primary key not null auto_increment comment '编号' ,
code_type varchar(50) not null comment '编码类型' ,
code_max int not null comment '最大值' ,
upper_code varchar(50) null comment '上级编码' ,
updateTime datetime DEFAULT now() comment '更新时间'
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci COMMENT = '最大编码次数记录';
- 创建编码生成函数 func_idx_code
drop FUNCTION if EXISTS func_idx_code;
create function func_idx_code(codeType varchar(50) ,upperCode varchar(50), len int )
returns VARCHAR(20)
begin
-- 定义变量
DECLARE max int DEFAULT 0 ;
DECLARE codeMax VARCHAR(20) ;
-- 查询最大值
if upperCode is null then
select (code_max+1) into max from pub_code_max where code_type = codeType and upper_code is null ;
else
select (code_max+1) into max from pub_code_max where code_type = codeType and upper_code = upperCode ;
end if ;
-- 判断是否存在 编码,如果没有则需要新建
if max is null or max =0 then
insert into pub_code_max (code_type,code_max,upper_code) VALUES(codeType,1,upperCode);
set max = 1;
end if ;
-- 更新最大编码值
if upperCode is null then
update pub_code_max set code_max = max,updateTime = now() where code_type = codeType and upper_code is null ;
else
update pub_code_max set code_max = max,updateTime = now() where code_type = codeType and upper_code = upperCode;
end if;
-- 格式化编码格式,补0
select LPAD(max, len, 0) into codeMax ;
-- 拼接完整编码
if upperCode is not null then
set codeMax = concat(upperCode,codeMax);
end if ;
return codeMax;
end ;
- 参数说明
codeType varchar(50) : 编码的类型,自定义即可,每次同一类型保持一致即可
upperCode varchar(50) : 上级编码
len int : 编码的长度
-- 模拟调用: 生成 0101001的下级编码,长度为4
select func_idx_code('idx_domain','0101001',4)
五、写在最后
此思路仅供参考,如有错误,感谢请指正讨论。