參考:https://www.jianshu.com/p/331b872e9c8f
1.建立一張存放的表
CREATE TABLE `sys_serial_number` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`module_name` varchar(50) DEFAULT NULL COMMENT '模塊名稱',
`module_code` varchar(50) DEFAULT NULL COMMENT '模塊編碼(唯一的)',
`config_templet` varchar(50) DEFAULT NULL COMMENT '訂單前綴',
`max_serial` varchar(32) DEFAULT NULL COMMENT '存放當前序列號的值',
`pre_max_num` varchar(32) DEFAULT NULL COMMENT '預生成序列號存放到緩存的個數',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='序列自增長表';
package ch.service.sys; import ch.common.util.CacheUtils; import ch.dao.sys.SerialNumDao; import ch.entity.sys.SystemSerialNumberEntity; import ch.util.DateUtils; import ch.util.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.concurrent.locks.ReentrantLock; /** * Description: * * @author cy * @date 2019年05月07日 13:23 * version 1.0 */ @Service public class SerialNumberServiceImpl implements SerialNumService { @Autowired private SerialNumDao serialNumDao; /** 日期格式 */ private String pattern = "yyyyMMddHHmmss"; /** 生成器鎖 */ private final ReentrantLock lock = new ReentrantLock(); /** 流水號格式化器 */ private DecimalFormat format = new DecimalFormat("00"); /** 預生成鎖 */ private final ReentrantLock prepareLock = new ReentrantLock(); /** 最小值 */ private int min = 0; /** 最大值 */ private long max = 10; /** 已生成流水號(種子) */ private long seed = min; /** 預生成數量 */ private int prepare = 4; /** 數據庫存儲的當前最大序列號 **/ long maxSerialInt = 0; /** 當前序列號是否為個位數自增的模式 **/ private String isAutoIncrement = "0"; /** 預生成流水號 */ HashMap<String, List<String>> prepareSerialNumberMap = new HashMap<>(); /** * 查詢單條序列號配置信息 * @param * @return */ @Override public SystemSerialNumberEntity find(SystemSerialNumberEntity entity) { return null; } /** * 根據模塊code生成預數量的序列號存放到Map中 * @param moduleCode 模塊code * @return */ @Transactional public List<String> generatePrepareSerialNumbers(String moduleCode){ //臨時List變量 List<String> resultList = new ArrayList<String>(prepare); lock.lock(); // 查詢數據庫最大maxSerialInt SystemSerialNumberEntity oneByCode = serialNumDao.findOneByCode(moduleCode); if(oneByCode == null){ throw new RuntimeException("不存在模塊code"); } this.maxSerialInt = Long.valueOf(oneByCode.getMaxSerial()); this.prepare = Integer.valueOf(oneByCode.getPreMaxNum()); try { for (int i = 0; i < prepare; i++) { maxSerialInt += 1; if(maxSerialInt > min && maxSerialInt < max){ seed = maxSerialInt; }else { // 如果動態數字長度大於模板中的長度 例:模板CF000 maxSerialInt 1000 seed = maxSerialInt = 0; } // 動態數字生成拼接 String formatSerialNum = format.format(seed); // 動態日期的生成拼接 if(StringUtils.isNotBlank(pattern)){ String date = DateUtils.getDate(pattern); formatSerialNum = date + formatSerialNum; } if(StringUtils.isNotBlank(oneByCode.getConfigTemplet())){ formatSerialNum = oneByCode.getConfigTemplet() + formatSerialNum; } resultList.add(formatSerialNum); } //更新數據 oneByCode.setMaxSerial(maxSerialInt + ""); serialNumDao.update(oneByCode); }catch (Exception e){ e.printStackTrace(); }finally { lock.unlock(); } return resultList; } /** * 根據模塊code生成序列號 * @param moduleCode 模塊code * @return 序列號 */ @Override @Transactional public String generateSerialNumberByModelCode(String moduleCode) { //預序列號加鎖 prepareLock.lock(); try{ //判斷內存中是否還有序列號 if(null != prepareSerialNumberMap.get(moduleCode) && prepareSerialNumberMap.get(moduleCode).size() > 0){ //若有,返回第一個,並刪除 return prepareSerialNumberMap.get(moduleCode).remove(0); } }catch (Exception e){ e.printStackTrace(); }finally { //預序列號解鎖 prepareLock.unlock(); } List<String> resultList = generatePrepareSerialNumbers(moduleCode); prepareLock.lock(); try { prepareSerialNumberMap.put(moduleCode, resultList); return prepareSerialNumberMap.get(moduleCode).remove(0); } finally { prepareLock.unlock(); } } }