生成流水号,在企业中可以说是比较常见的需求,尤其是订单类业务。
一般来说,需要保证流水号的唯一性。
如果没有长度和字符的限制,那么直接使用UUID生成一个唯一字符串即可,具体可参考我的这篇文章:java生成类似token的唯一随机字符串

也可以直接使用数据库表中的主键,主键就是唯一的。

那么,如果限制了流水号必须多少位,这种怎么生成呢?

可以采用"前缀+日期+数字"的方式(ps:此方式是需要用到缓存的)
前缀:为了更好的标识这个流水号是属于哪种类型;
日期:为了防止重复;
数字:为了表示当前的流水所处序号。

需求:生成一个17位数的唯一流水号,“LSH”+yyyyMMdd+6位数字

下面,就是具体的代码实现,具体内容可参考注释

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.concurrent.atomic.AtomicInteger;public class SerialNoTest {public static void main(String[] args) {String serialNo = generateSerialNo();System.out.println("生成的流水号:"+serialNo);}/*** 生成17位唯一流水号,"LSH"+yyyyMMdd+6位数字* 6位数字,如:000001* @return*/private static String generateSerialNo(){//定义需要返回的流水号String serialNo = null;//先查询到今天的日期,格式:"yyyyMMdd"String todayDate = new SimpleDateFormat("yyyyMMdd").format(new Date());//固定字母前缀 拼接 今天日期,组成新的完整的前缀,也就是缓存的keyString cacheKey = "LSH"+todayDate;//再通过key查询缓存有没有num数据,缓存操作根据自身项目封装工具类Long codeNum = cacheService.getCache(cacheKey, Long.class);//如果缓存查询有值,数值+1,再赋值给下一个流水号if (null != codeNum) {codeNum = codeNum + 1L;} else {//如果缓存查询没值,直接赋值为1codeNum = 1L;}//流水号 = 缓存key + 拼接的数值 = 前缀 + 日期 + 拼接的数值serialNo = getCodeOfSix(cacheKey, codeNum.intValue());//设置缓存,调用此方法,会自动将key所对应的value+1,保存时长:今天剩余的时间cacheService.incr(cacheKey, getSeconds());return serialNo;}/*** 将数值拼接成对应的位数* @param prefix  前缀:"LSH"+yyyyMMdd* @param nowNum  当前要生成的数字* @return 拼接好的流水号*/public static String getCodeOfSix(String prefix,int nowNum ) {//需要返回的codeStringBuilder codeSb = new StringBuilder();//需要拼接的数字StringBuilder numSb = new StringBuilder();//封装的数字对象,里面 value 加了 volatile关键字,保证了线程安全AtomicInteger count = new AtomicInteger(nowNum);//将数值补足为6位字符串if (count.get() < 10) {numSb.append("00000").append(count.get());} else if(count.get() < 100){numSb.append("0000").append(count.get());}else if(count.get() < 1000){numSb.append("000").append(count.get());}else if(count.get() < 10000){numSb.append("00").append(count.get());}else if(count.get() < 100000){numSb.append("0").append(count.get());} else if (count.get() >= 100000) {numSb.append(count.get());}//先拼接前缀codeSb.append(prefix);//再拼接数字codeSb.append(numSb);return codeSb.toString();}/*** 获取当天结束还剩余多少秒* @return*/public static int getSeconds(){//获取今天当前时间Calendar curDate = Calendar.getInstance();//获取明天凌晨0点的日期Calendar tommorowDate = new GregorianCalendar(curDate.get(Calendar.YEAR),curDate.get(Calendar.MONTH), curDate.get(Calendar.DATE) + 1,0, 0, 0);//返回 明天凌晨0点 和 今天当前时间 的差值(秒数) return (int)(tommorowDate.getTimeInMillis() - curDate .getTimeInMillis()) / 1000;}
}

假如今天是2021年4月22日,运行项目,生成的第1个流水号则为:LSH20210422000001
第2个流水号则为:LSH20210422000002,依次类推。

需要注意的是:
如果限制了位数,6位数字每天最多能生成10w个流水号,所以,这个数字位数根据具体业务量进行调整。
如果每天的生成数量量不到1w,那么使用4位数字即可。

如何根据日期+数字生成流水号相关推荐

  1. java oracle 流水号_Oracle生成流水号函数

    一.参考 1:日期范围上 smalldatetime的有效时间范围1900/1/1~2079/6/6 datetime的有效时间范围1753/1/1~9999/12/31 2:精准度上 smallda ...

  2. sql server 按照日期自动生成单据编号的函数

    一.sql server 按照日期自动生成单据编号的函数,格式为##08080001,##表示打头的单据字符,然后是年月和流水编号. 二.传入的参数为单据的打头字符和生成单据的日期 三.一般的调用格式 ...

  3. 根据时间戳生成编号_使用雪花算法生成流水号!

    前言"在分布式系统中常见的问题就是如何生成流水号,一般情况下会有专门的流水号系统,不过在开发过程中或者开发早期不一定会有专门流水号系统,在这里介绍下我所使用的流水号生成器--雪花算法&quo ...

  4. 用SerialNumber生成流水号

    在很多程序的应用中,有许多的地方会用到流水号,我写了个专门用来生成流水号的类 使用: SerialNumber sn=new SerialNumber(); sn.getSerialNum(table ...

  5. 使用redis生成流水号

    转载请标明出处: 使用redis生成流水号_付付讶的博客-CSDN博客 本文出自使用redis生成流水号_付付讶的博客-CSDN博客 公司需求:生成14位时间+redis流水3位+"-&qu ...

  6. Oracle 生成流水号

    辅助表(RUL_SEQUENCE): 表中数据如图: 辅助存储过程(Proc_GetSeqence): CREATE OR REPLACE PROCEDURE Proc_GetSeqence(SeqC ...

  7. 帮我用Java写一个生成流水号的方法

    我可以给你提供一个使用Java来生成流水号的简单方法: 使用java.util.UUID类来生成一个唯一的字符串: 使用java.time.LocalDateTime类来获取当前的日期和时间: 将上述 ...

  8. mysql 生成流水号 存储过程 订单编号

    用存储过程生成流水号是很常用的,这里以生成订单编号的流水号作为示例.(新的一天的流水号从1开始,如:今天的订单编号是CD2013010900014,下一个订单编号将是CD2013010900015:明 ...

  9. sql自动生成流水号

    创建表 CREATE TABLE CreateSerialNo (CreateSerialNoId INT PRIMARY KEY IDENTITY(1,1),TableName VARCHAR(60 ...

  10. P1132 数字生成游戏

    题目描述 小明完成了这样一个数字生成游戏,对于一个不包含00的数字ss来说,有以下33种生成新的数的规则: 将ss的任意两位对换生成新的数字,例如143143可以生成314,413,134314,41 ...

最新文章

  1. 这张程序员情绪波动图,未免太真实了! | 每日趣闻
  2. C#中的Params、ref、out的区别
  3. 全球及中国人寿保险产业盈利能力与十四五营销策略咨询报告2022版
  4. android底层rsa加密,android 下RSA加密解密
  5. MSU发布2018年视频压缩评比报告
  6. threejs坐标转换
  7. android-pageviewer实现linearlayout的切换
  8. mysql 字段 浮点_MySQL浮点数据字段不接受每个浮点数?如何解决这个问题?
  9. 判断服务器芯片还是民用芯片,抢鲜看,Xeon E3-1230对比I7 2600评测
  10. 论文阅读笔记(五)——FD-MOBILENET
  11. Java试题库(含答案)
  12. K3 Cloud 常用数据表整理
  13. HTML制作用户登录界面
  14. 网站推广优化教程100条(完整版)
  15. 校园锐捷路由器使用指南
  16. 一小心删除了系统文件NTDETECT.COM怎么办
  17. python 开放端口探测工具
  18. 基于Qt ffmpeg opengl开发跨平台安卓实时投屏软件
  19. vagrant启动失败解决
  20. 可能是最全的人工智能入门书单(附PDF链接)

热门文章

  1. 模拟登陆webqq总结(二)
  2. MapInfo教程--二次开发入门
  3. Struts2通配符详解
  4. Qt是什么?Qt简介(非常全面)
  5. QQ连连看6.0 逆向分析
  6. 视频教程-华为HCNP/HCIP路由交换高级网络工程师-华为认证
  7. BP(Back Propagation)神经网络——原理篇
  8. Excel函数公式大全以及用法
  9. 富士通Fujitsu DPK320 打印机驱动
  10. docker安装DM8