在实际的开发中,可能会有根据一定的规则生成流水号的需求(比如根据根据公司编码和日期生成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; } }