订单Id的生成

生成规则

我们在做订单模块的时候通常将订单定义为String类型的,因为订单号是有一系列的编码规则的。

首先我们假定订单有16位码。我们将这16位码分成3部分进行一个对应

  • 前8位,时间日期如 :20190603
  • 中间 6 位 ,自增长序列从000001到999999保持增长
  • 后 2 位,分库分表位

这里的分库分表后续会单独写。这里定义2位00

订单Id生成模拟

新建一个StringBuilder用来存放字符串

StringBuilder stringBuilder = new StringBuilder();

时间日期的8位模拟实现

//年月日    8位
LocalDateTime now = LocalDateTime.now();
String nowDate = now.format(DateTimeFormatter.ISO_DATE).replace("-","");
stringBuilder.append(nowDate);

自增长的 6 位实现
自增长的 6 位需要借助持久化来实现,首先需要建立一个序列增长的表,这个表的作用就是来控制我们表的6位增长。建表信息如下:

CREATE TABLE `sequence_info` (
  `name` varchar(255) NOT NULL DEFAULT '0',
  `current_value` int(11) NOT NULL DEFAULT '0',
  `step` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='订单编号增长序列信息';

各个字段的解释如下

  • name : 标志自增长的信息名字 current_value : 我们要获取的信息值
  • step :信息增长值

建立字段增长表
有了表之后我们就有了一个思路:首先我们要给数据库表中一个初始值,让current_value从0开始增加,step为1。

insert into sequence_info(name,current_value,step) values("order_info","0","1");

接下来我们通过业务逻辑实现

我们先查询到order_info的所在信息,因为我们的自增长id序列可能要设置多个属性,比如商品id也可以通过这种方进行设置。所以我们设置了name这个字段保证我们在用order_info的时候来查找到。这样就可以获取到当前的增长序列

 int sequence = 0;
//获取Sequence
SequenceDO sequenceDO = sequenceDOMapper.getSequenceByName("order_info");
sequence = sequenceDO.getCurrentValue()

注意我们在查找的时候应该保证给数据库加锁,下面是sequenceDOMapper.getSequenceByName方法的sql语句

<select id="getSequenceByName" parameterType="java.lang.String" resultMap="BaseResultMap">
    select
    from sequence_info
    where name = #{name,jdbcType=INTEGER} for update
</select>

接着对current_value + step 设置下次的增长序列

sequenceDO.setCurrentValue(sequenceDO.getCurrentValue()+sequenceDO.getStep());
sequenceDOMapper.updateByPrimaryKey(sequenceDO);

最后对不足6位的数字进行一个0的拼接

  String sequenceStr = String.valueOf(sequence);
  for (int i = 0; i <6 - sequenceStr.length(); i++) {
      stringBuilder.append(0);
  }
  stringBuilder.append(sequenceStr);

如果说我们的表增长超过了6位,我们就让它的下一次继续从0开始循环。

Integer nextSequence = sequenceDO.getCurrentValue()+sequenceDO.getStep() ;
if (nextSequence >= 1000000) {
        sequenceDO.setCurrentValue(0);
        sequenceDOMapper.updateByPrimaryKey(sequenceDO);
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章