在项目开发的实际过程中,经常会遇到需要生成id,或者订单号的业务,如果只是保证唯一,我们在分布式下,只需要考虑雪花算法就可以轻松实现,那么怎么去生成有规则有顺序的单号呢。
表结构
注:数据库字段中出现tenant_id
及version_
可以无视,晨使用的jpa框架,其他框架可以自行扩展。
CREATE TABLE `t_generator` (
`id` bigint(20) NOT NULL,
`tenant_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`version_` bigint(20) NULL DEFAULT NULL,
`seq_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`expression` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`value` bigint(20) NULL DEFAULT NULL,
`increment` bigint(20) NULL DEFAULT NULL,
`length` int(11) NOT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
实体类
@Data
public class GeneratorEO{
private Long id;
/**
* 序列名称
*/
private String seqName;
/**
* 执行表达式
*/
private String expression;
/**
* 当前值
*/
private Long value;
/**
* 自增值
*/
private Long increment;
/**
* 序号的长度(位数)
*/
private int length;
}
核心逻辑
@Transactional
@Override
public Object get(String seqName, String tenantId) {
GeneratorEO generatorEO = baseRepository.findOne((root, criteriaQuery, criteriaBuilder) ->
criteriaBuilder.equal(root.get(GeneratorEO.SEQ_NAME), seqName)).orElse(null);
Object value = null;
if (generatorEO != null) {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Expression exp;
Long oldValue = generatorEO.getValue();
String expression = generatorEO.getExpression();
context.setVariable("tenantId",generatorEO.getTenantId());
if(generatorEO.getLength()>0){
context.setVariable("value",String.format("%0"+generatorEO.getLength()+"d",oldValue));
}else{
context.setVariable("value",oldValue);
}
if (StringUtils.isNotBlank(expression)) {
exp = parser.parseExpression(expression);
} else {
exp = parser.parseExpression("#value");
}
value = exp.getValue(context);
exp = parser.parseExpression("#value + #increment");
context.setVariable("value",oldValue);
context.setVariable("increment",generatorEO.getIncrement());
Long newValue = (Long)exp.getValue(context);
generatorEO.setValue(newValue);
baseRepository.flush();
}
return value;
}