手写个递增号码生成器

简介: 每家船公司的文件序列号从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())
相关文章
|
3月前
|
语音技术 数据安全/隐私保护
语音识别,猜猜心里数字讲解,猜数字的组合,判断语句的嵌套,嵌套语句使用很简单,我们写一个外层嵌套的条件,利用缩进,满足条件,才会执行条件2,判断语句综合案例,如何产生变量的随机数字,while循环应用
语音识别,猜猜心里数字讲解,猜数字的组合,判断语句的嵌套,嵌套语句使用很简单,我们写一个外层嵌套的条件,利用缩进,满足条件,才会执行条件2,判断语句综合案例,如何产生变量的随机数字,while循环应用
|
5月前
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
2569. 更新数组后处理求和查询(模板 + 普通线段树熟练掌握)
|
运维 Shell Python
【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)(一)
【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)
127 0
|
5月前
|
SQL 算法 vr&ar
☆打卡算法☆LeetCode 182. 查找重复的电子邮箱 算法解析
☆打卡算法☆LeetCode 182. 查找重复的电子邮箱 算法解析
☆打卡算法☆LeetCode 182. 查找重复的电子邮箱 算法解析
|
12月前
|
存储 算法 索引
【每日挠头算法题(3)】字符串解码|数组中重复的数字
【每日挠头算法题(3)】字符串解码|数组中重复的数字
|
运维 Shell Perl
【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)(二)
【运维知识高级篇】超详细的Shell编程讲解2(变量切片+统计变量长度+字串删除+字串替换+七种方法进行数值运算+整数比较+多整数比较+文件判断+字符串比对+正则比对+配合三剑客的高阶用法)(二)
125 0
|
Rust 自然语言处理 算法
【算法】1342. 将数字变成 0 的操作次数(多语言实现)
给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
|
Java
用Java实现3D随机选号码的功能
- ## 需要用到Scanner语句 - ## 需要用到for循环 - ## 需要用到Math方法
504 0
用Java实现3D随机选号码的功能