基于数据库的主键_订单号生成策略

homeant | 2019-10-30 16:58 浏览99

在项目开发的实际过程中,经常会遇到需要生成id,或者订单号的业务,如果只是保证唯一,我们在分布式下,只需要考虑*雪花算法*就可以轻松实现,那么怎么去生成有规则有顺序的单号呢。

表结构

表结构

注:数据库字段中出现tenant_idversion_可以无视,晨使用的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;
}

参考资料

Spring Expression Language