手写个递增号码生成器

简介: 每家船公司的文件序列号从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())
相关文章
|
5月前
|
存储 数据库
【随手记】顺序I/O和随机I/O的定义和区别
【随手记】顺序I/O和随机I/O的定义和区别
183 1
|
6月前
|
数据安全/隐私保护
在线随机密码生成器源码
纯HTML,该去的已去掉,该简化的简化,最高支持32位混合随机密码生成。
104 2
在线随机密码生成器源码
|
6月前
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
|
6月前
7-7 念数字 (15 分)(用数组简化判断过程)
7-7 念数字 (15 分)(用数组简化判断过程)
50 0
宜搭中,你可以通过设置条件和循环来实现流水号到固定值时进行循环的功能
宜搭中,你可以通过设置条件和循环来实现流水号到固定值时进行循环的功能
236 2
|
11月前
|
算法 测试技术 C#
C++单调向量算法:得到山形数组的最少删除次数
C++单调向量算法:得到山形数组的最少删除次数
通话记录生成器
首先,看下面图的中间绿色图标和字母。第一步:批量放入通话号码。第二步:选择通话时间范围。第三步:选择通话时间长度。第四步:选择一种通话类型。第五步:批量生成通话记录。最后提示:认真仔细看前面的第一个图。 
通话记录生成器
|
前端开发
前端学习案例5-迭代器和生成器5 原
前端学习案例5-迭代器和生成器5 原
73 0
前端学习案例5-迭代器和生成器5 原