手写个递增号码生成器

简介: 每家船公司的文件序列号从00001开始,最大长度五位数字,超过99999就重置为00001

一 业务需求

每家船公司的文件序列号从00001开始,最大长度五位数字,超过99999就重置为00001

二 分析

提到流水号,我们可能会想到数据库序列,但是这里要求每一个船公司都要求有一个流水号,如果是每一个船公司都创建一个序列,显然是不正确的,另外,序列其实是从1开始而不是00001,那如何实现这个呢,用字符串拼接可以,但是想起来就是需要一些if else,较为麻烦。
最终选择了方案时,创建一个数据库表,每一个船公司都对应一条数据,且每一个船公司都记录他的流水号,这样就能实现流水号的处理。
另外选择Strings.padStart(seqNo, length, '0');方法对流水号进行补全

三 实现

  1. 新建数据库表CNF_NUMBER

    CREATE TABLE "CNF_NUMBER" 
    (  
      "ID" VARCHAR2(32 CHAR), 
      "CREATED_BY" VARCHAR2(128 CHAR), 
      "CREATED_DATE" TIMESTAMP (6), 
      "LAST_MODIFIED_BY" VARCHAR2(128 CHAR), 
      "LAST_MODIFIED_DATE" TIMESTAMP (6), 
      "VERSION" NUMBER(19,0), 
      "CODE" VARCHAR2(128 CHAR), 
      "MIN_VALUE" NUMBER(19,0), 
      "MAX_VALUE" NUMBER(19,0), 
      "INCREMENT_BY" NUMBER(19,0), 
      "CURRENT_VALUE" NUMBER(19,0), 
       CONSTRAINT "CNF_NUMBER_PK" PRIMARY KEY ("ID")
    );
    
     COMMENT ON TABLE "CNF_NUMBER"IS '自增流水表';
    
     COMMENT ON COLUMN "CNF_NUMBER"."ID" IS '主键';
    
     COMMENT ON COLUMN "CNF_NUMBER"."CREATED_BY" IS '创建人';
    
     COMMENT ON COLUMN "CNF_NUMBER"."CREATED_DATE" IS '创建时间';
    
     COMMENT ON COLUMN "CNF_NUMBER"."LAST_MODIFIED_BY" IS '最后修改人';
    
     COMMENT ON COLUMN "CNF_NUMBER"."LAST_MODIFIED_DATE" IS '最后修改时间';
    
     COMMENT ON COLUMN "CNF_NUMBER"."VERSION" IS '数据行版本,用于乐观锁控制。';
    
     COMMENT ON COLUMN "CNF_NUMBER"."CODE" IS '序列代码';
    
     COMMENT ON COLUMN "CNF_NUMBER"."MIN_VALUE" IS '最小值';
    
     COMMENT ON COLUMN "CNF_NUMBER"."MAX_VALUE" IS '最大值';
    
     COMMENT ON COLUMN "CNF_NUMBER"."INCREMENT_BY" IS '步长';
    
     COMMENT ON COLUMN "CNF_NUMBER"."CURRENT_VALUE" IS '当前值';
  2. 创建递增业务类及逻辑实现

    /**
     * 递增号码生成器
     *
     * @author 子羽
     */
    @Service
    public class NumberService {
    
        @Autowired
        private NumberRepository numberRepository;
    /**
     * 从指定的序列中获取下一个值。
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public long countNextValueFrom(String code) {
        return countMessageNextNumberFrom(code).getCurrentValue();

    }
```


```
/**
 * 从指定的序列中获取下一个值。
 */
private synchronized Number countMessageNextNumberFrom(String code) {
    Number num = this.numberRepository.findByCode(code);
    if (num == null) {
        num = Number.newInstance();
        num.setCode(code);
        num.setMaxValue(99999L);
    }

    // 循环直到获取到正确的值,避免并发环境下无法正确获取号码的问题
    while (true) {
        try {
            num = this.numberRepository.saveAndFlush(num.incrementAndGet());
            break;
        } catch (OptimisticLockException ole) {
            num = this.numberRepository.findOne(num.getId());
            continue;
        }
    }
    return num;

}
```

  这里要注意的是,并发时出现乐观锁异常num取当前的流水号
  1. 达到最大值回归最小值的逻辑处理

      public Number incrementAndGet() {
          if (this.currentValue == this.maxValue) {
              this.currentValue = this.minValue;
          }
    
          this.currentValue += this.incrementBy;
          return this;
      }
    1. 使用Strings.padStart()填充流水号

       private String getSeq(String seqName, int length) {
           String seqNo = String.valueOf(this.numberService.countNextValueFrom(seqName));
           return Strings.padStart(seqNo, length, '0');
           
      
       
       public String createSerialNo(String carrierId) {
           return getSeq(carrierId, 5);
       }
      

    5.调用

     // 获得创公司流水号
     String seqNo = this.createSerialNo(eir.getCarrierId())
相关文章
|
8月前
|
数据库
基于Redisson的RAtomicLong实现全局唯一工单号生成器
这次我们采用了 Redisson 的 RAtomicLong 来生成一个以固定字符加上年月为键的自增数。随后,将自增数转换为36进制字符串,以年月和36进制字符串拼接形成全局唯一的工单号。
234 1
基于Redisson的RAtomicLong实现全局唯一工单号生成器
|
存储 算法 索引
【每日挠头算法题(3)】字符串解码|数组中重复的数字
【每日挠头算法题(3)】字符串解码|数组中重复的数字
|
人工智能
一文搞懂候选码、主码、全码、外码、主属性、主键、主关键字、非主属性清晰总结
一文搞懂候选码、主码、全码、外码、主属性、主键、主关键字、非主属性清晰总结
通话记录生成器
首先,看下面图的中间绿色图标和字母。第一步:批量放入通话号码。第二步:选择通话时间范围。第三步:选择通话时间长度。第四步:选择一种通话类型。第五步:批量生成通话记录。最后提示:认真仔细看前面的第一个图。 
通话记录生成器
如何用正则表达式判断手机号格式正不正确
如何用正则表达式判断手机号格式正不正确
151 0
|
存储 索引
零基础VB教程054期:随机抽取不重复的值
零基础VB教程054期:随机抽取不重复的值
111 0
手写支持函数、日期和正则的深拷贝
手写支持函数、日期和正则的深拷贝
167 0
|
Java
用Java实现3D随机选号码的功能
- ## 需要用到Scanner语句 - ## 需要用到for循环 - ## 需要用到Math方法
548 0
用Java实现3D随机选号码的功能