訂單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);
 }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章