在实际的开发中,可能会有根据一定的规则生成流水号的需求(比如根据根据公司编码和日期生成4位流水号)我们可以把公司和日期联合起来作为一个业务编码,把这个业务编码和序列的值存储到数据库中,每次需要生成流水号的时候根据公司和日期联合起来生成的这个业务编码去数据库里边去查,若有记录的话就把记录的话就把对应的序列值返回,然后序列的值加一,若根据对应的业务编码查询不到相应的记录就把流水号对应的最小的值返回,然后在数据库中插入相应的记录
缺点:在集群环境下可能导致在两台服务器上生成的流水号一致的情况(解决方法是在数据库中使用存储过程来生成随机数,在存储过程中进行同步)
这种场景使用类似BerkeleyDB这种K,Value对数据库来实现是最好的选择(下面先贴出使用传统的关系型数据库来实现的例子,使用BerkeleyDB的例子随后会给出)
import java.math.BigDecimal; import org.quickbundle.project.RmProjectHelper; import org.quickbundle.project.common.vo.RmCommonVo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * 流水号生成器 * @author Administrator * */ public class SeriaNumberGenerator { Logger logger = LoggerFactory.getLogger(SeriaNumberGenerator.class); private static int MAX_VALUE=9999; private static int MIN_VALUE = 1; /** * 根据业务标识符取到下一个流水号 * @param businessCode * @return */ public synchronized String getNextVal(String businessCode){ int currentValue ; int nextValue ; RmCommonVo comonVo =null; try{ comonVo = RmProjectHelper.getCommonServiceInstance().doQueryForObject("select CURRENT_VALUE from SERIAL_NUMBER WHERE KEY ='"+businessCode+"'"); }catch( org.springframework.dao.EmptyResultDataAccessException ex){ logger.error("结果集为空,SpringJdbc抛出异常,不影响程序执行..."); } //该key不存在(存放进去) if(comonVo == null ||comonVo.size()== 0){ currentValue= MIN_VALUE; nextValue = currentValue +1; RmProjectHelper.getCommonServiceInstance().doUpdate(" insert into SERIAL_NUMBER (KEY, CURRENT_VALUE ) VALUES ('"+businessCode+"','"+nextValue+"')"); } // else{ currentValue = ((BigDecimal)comonVo.get("CURRENT_VALUE")).intValue(); //已经到达最大值 if(MAX_VALUE==currentValue){ nextValue =MIN_VALUE; }else{ nextValue = currentValue+1; } RmProjectHelper.getCommonServiceInstance().doUpdate("update SERIAL_NUMBER set CURRENT_VALUE='"+nextValue+"' WHERE KEY='"+businessCode+"'"); } String finalValue = this.formatString(currentValue); return finalValue ; } public SeriaNumberGenerator(){ } /** * 将数字转换为字符串(当不足4位时高位补0) * @param input * @return */ public String formatString(int input){ String result ; //大于1000时直接转换成字符串返回 if(input > 1000){ result = input+""; }else{//根据位数的不同前边补不同的0 int length = (input +"").length(); if(length == 1){ result = "000"+input; }else if(length ==2){ result = "00"+input; }else{ result = "0"+input; } } return result; } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现