JAVA自定义规则生成唯一ID

简介: 本文以类型和订单时间为例,SQL方案和Redis方案

自定义规则生成唯一ID(方案一:通过SQL生成)

  • 场景:

    生成物流唯一ID,要求根据创建的订单时间及该订单所属类型,举例:

有一个订单类型为‘普货’,该订单时间为‘2022-07-19 00:00:00’,且该订单为7月底第一订单,则物流ID为:P-2207000001,后面同一类型同一个月的物流ID自增,P-2207000002,规则:类型-时间-指定位数数字字符(type-yyMM-00000...)
  • 实战:
    现有类型:集团外整车(J-)、普货(P-)、零部件(L-)
    规则:类型yyMM六位自增数字
    实现:
    通过SQL直接获取下一个物流唯一ID

image.png

    SELECT (CASE
     WHEN ID_GEN IS NULl AND '零部件'= #{bigType} THEN 'L-'||TO_CHAR(#{orderDate}, 'yyMM')||'000001'
     WHEN ID_GEN IS NULl AND '集团外整车'= #{bigType} THEN 'J-'||TO_CHAR(#{orderDate}, 'yyMM')||'000001'
     WHEN ID_GEN IS NULl AND '普货'= #{bigType} THEN 'P-'||TO_CHAR(#{orderDate}, 'yyMM')||'000001'
     WHEN ID_GEN IS NOT NULl AND '零部件'= #{bigType} THEN 'L-'|| TO_CHAR(#{orderDate}, 'yyMM')|| ID_GEN
     WHEN ID_GEN IS NOT NULl AND '集团外整车'= #{bigType} THEN 'J-' || TO_CHAR(#{orderDate}, 'yyMM')||ID_GEN
     WHEN ID_GEN IS NOT NULl AND '普货'= #{bigType} THEN 'P-'|| TO_CHAR(#{orderDate}, 'yyMM')|| ID_GEN
     ELSE NULL END) AS wayWillNo
  FROM (
      SELECT TO_CHAR(TO_NUMBER(MAX(regexp_replace(WAYBILL_NO, '[^0-9]')))+1, 'fm000000') AS ID_GEN FROM OB_ORDER  WHERE BIG_TYPE=#{bigType} AND TO_CHAR(DTORDER_DATE, 'yyyyMM')=TO_CHAR(#{orderDate}, 'yyyyMM')
    )
</select>  

考虑使用的并发问题,导致取到生成相同的ID,获取ID通过该方法获取,加锁,并预生成部分唯一ID


@Service
public class SeqService {

    private final ReentrantLock lock = new ReentrantLock();

    private static final Map<String,List<String>> waybillMap=new ConcurrentHashMap<>();

    @Autowired
    private OrderMapper orderMapper;
   
   public String  genWaybillNo(String bigType, Date dtOrderDate){
       lock.lock();
       try {
           List<String> list = waybillMap.get(bigType + DateUtils.format(dtOrderDate, "yyMM"));
           if (CollectionUtil.isEmpty(list)) {
               if(list==null){
                   list=new ArrayList<>();
               }
               String waybillNo = orderMapper.genWaybillNo(bigType, dtOrderDate);
               String pre = ("集团外整车".equals(bigType) ? "J-"
                       : ("普货".equals(bigType) ? "P-" : "L-") )+ DateUtils.format(dtOrderDate, "yyMM");
               for (int i = 0; i < 9; i++) {
                   waybillNo = getLastWayBillNo(pre, waybillNo);
                   list.add(waybillNo);
               }
               return waybillNo;
           } else {
               String waybillNo = list.stream().findFirst().get();
               list.remove(waybillNo);
               waybillMap.put(bigType + DateUtils.format(dtOrderDate, "yyMM"), list);
               return waybillNo;
           }
       }finally {
           System.out.println("generate seq unlock");
           lock.unlock();
       }

   }
  //生成下一个
   private static String getLastWayBillNo(String pre,String waybillNo){
       String number = StrUtil.removePrefix(waybillNo, pre);
       if (!StringUtils.isEmpty(number)) {
           int n = number.length(); //取出字符串的长度
           int num = Integer.parseInt(number) + 1; //将该数字加一
           String added = String.valueOf(num);
           n = Math.min(n, added.length());
           //拼接字符串
           return waybillNo.subSequence(0, waybillNo.length() - n) + added;
       } else {
           throw new NumberFormatException();
       }
   }

}

效果:
image.png

自定义规则生成唯一ID(方案二:通过redis生成)

  • 将固定前缀+类型+yyMM作为key,获取ID时,如果为空,拼接生成第一个ID,并set到redis,如果不为空,将取到的值,生成下一个ID并set的redis,生成方法请参考方案一。
  • 或者reids只存数字 incr,前缀自己拼接
目录
相关文章
|
2月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
110 4
|
2月前
|
存储 Java Go
【Java】(3)8种基本数据类型的分析、数据类型转换规则、转义字符的列举
牢记类型转换规则在脑海中将编译和运行两个阶段分开,这是两个不同的阶段,不要弄混!
204 2
|
2月前
|
安全 Java
Java异常处理:程序世界的“交通规则
Java异常处理:程序世界的“交通规则
331 98
|
4月前
|
Java 数据库 C++
Java异常处理机制:try-catch、throws与自定义异常
本文深入解析Java异常处理机制,涵盖异常分类、try-catch-finally使用、throw与throws区别、自定义异常及最佳实践,助你写出更健壮、清晰的代码,提升Java编程能力。
|
5月前
|
XML 人工智能 Java
java通过自定义TraceId实现简单的链路追踪
本文介绍了如何在Spring Boot项目中通过SLF4J的MDC实现日志上下文traceId追踪。内容涵盖依赖配置、拦截器实现、网关与服务间调用的traceId传递、多线程环境下的上下文同步,以及logback日志格式配置。适用于小型微服务架构的链路追踪,便于排查复杂调用场景中的问题。
239 0
|
Java
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
java实现从HDFS上下载文件及文件夹的功能,以流形式输出,便于用户自定义保存任何路径下
386 34
|
Java
在 Java 中捕获和处理自定义异常的代码示例
本文提供了一个 Java 代码示例,展示了如何捕获和处理自定义异常。通过创建自定义异常类并使用 try-catch 语句,可以更灵活地处理程序中的错误情况。
385 1
|
Java
在 Java 中,如何自定义`NumberFormatException`异常
在Java中,自定义`NumberFormatException`异常可以通过继承`IllegalArgumentException`类并重写其构造方法来实现。自定义异常类可以添加额外的错误信息或行为,以便更精确地处理特定的数字格式转换错误。
228 1
|
安全 Java
如何在 Java 中创建自定义安全管理器
在Java中创建自定义安全管理器需要继承SecurityManager类并重写其方法,以实现特定的安全策略。通过设置系统安全属性来启用自定义安全管理器,从而控制应用程序的访问权限和安全行为。
319 1
|
Java
让星星⭐月亮告诉你,自定义定时器和Java自带原生定时器
定时器是一种可以设置多个具有不同执行时间和间隔的任务的工具。本文介绍了定时器的基本概念、如何自定义实现一个定时器,以及Java原生定时器的使用方法,包括定义定时任务接口、实现任务、定义任务处理线程和使用Java的`Timer`与`TimerTask`类来管理和执行定时任务。
420 3