在實際的開發中,可能會有根據一定的規則生成流水號的需求(比如根據根據公司編碼和日期生成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; } }