概述
在系統內部或與其他系統進行對接對編碼有一定自定義規則,包括批次號、訂單號,比如 PCH20170727152245000001 編碼規范 = 開頭字母 + 年月日時分秒 + 序號 ,使用存儲過程和不使用存儲過程兩種方式,數據都是存在 mysql 數據庫中。
詳細
一、准備工作
1、訂單號數據存儲在 Mysql 數據庫中,需要安裝 Mysql 數據庫。
2、使用數據庫存儲過程生成編碼和不使用存儲過程在代碼中生成編碼,相同的是編碼都是保存在數據庫中。
二、程序實現
1、程序截圖

2、實現思路
使用存儲過程:在存儲過程中進行查詢和插入
不使用存儲過程:在代碼中先查詢出來再進行插入
都是在數據庫進行查詢,然后插入
3、主要代碼
存儲過程如下:
BEGIN
-- 當前日期
DECLARE
currentDate VARCHAR (15);
-- 離現在最近的滿足條件的編碼
DECLARE
oldCode VARCHAR (25) DEFAULT '';
-- oldCode的流水號
DECLARE
maxNo INT DEFAULT 0;
IF num = 4 THEN
-- yyyy
SELECT
DATE_FORMAT(NOW(),'%Y') INTO currentDate;
ELSEIF num = 6 THEN
-- yyyymm
SELECT
DATE_FORMAT(NOW(),'%Y%m') INTO currentDate;
ELSEIF num = 8 THEN
-- yyyymmdd
SELECT
DATE_FORMAT(NOW(),'%Y%m%d') INTO currentDate;
ELSEIF num = 12 THEN
-- yyyymmddHHii
SELECT
DATE_FORMAT(NOW(),'%Y%m%d%H%i') INTO currentDate;
ELSEIF num = 14 THEN
-- yyyymmddHHiiss
SELECT
DATE_FORMAT(NOW(),'%Y%m%d%H%i%s') INTO currentDate;
END
IF;
-- 顯示最后一條數據
SELECT
IFNULL(code,'') INTO oldCode
FROM
code_test
WHERE
SUBSTRING(code,1,preLen) = pre
AND SUBSTRING(code,(preLen + 1),num) = currentDate
AND LENGTH(code) = preLen + num + noLen
ORDER BY
id DESC
LIMIT 1;
-- 編碼不為''截取編碼的最后noLen位
IF oldCode != '' THEN
SET maxNo = CONVERT(
SUBSTRING(oldCode, - noLen),
DECIMAL
);
END
IF;
-- 如果流水號不足noLen位,用0填充左邊
SELECT
CONCAT(
pre,
currentDate,
LPAD((maxNo + 1), noLen, '0')
) INTO newCode;
-- 插入數據
INSERT INTO
code_test (code)
VALUES
(newCode);
SELECT
newCode;
END
入參為:
IN pre VARCHAR(32), IN preLen INT, IN num INT, IN noLen INT, OUT newCode VARCHAR(32)
不使用存儲過程代碼如下:
//代碼同步,防止高並發
private final static ReentrantLock lock;
static{
lock = new ReentrantLock();
}
/**
* 不使用存儲過程
*/
@Test
public void codeTest2(){
Map<String, Object> map = new HashMap<String, Object>();
String pre = "PCH";
Integer preLen = 3;
Integer num = 4;
Integer noLen = 4;
Date curr = new Date();
SimpleDateFormat formatter = null;
switch (num) {
case 4:
formatter = new SimpleDateFormat("yyyy");
break;
case 6:
formatter = new SimpleDateFormat("yyyyMM");
break;
case 8:
formatter = new SimpleDateFormat("yyyyMMdd");
break;
case 12:
formatter = new SimpleDateFormat("yyyyMMddHHmm");
break;
case 14:
formatter = new SimpleDateFormat("yyyyMMddHHmmss");
break;
default:
break;
}
String currentDate = formatter.format(curr);
map.put("pre", pre);
map.put("preLen", preLen);
map.put("num", num);
map.put("noLen", noLen);
map.put("currentDate", currentDate);
lock.lock();
String newCode = "";
String newNo = "";
try {
String oldCode = codeTestDao.getOldCode(map);
if (StringUtils.isEmpty(oldCode)) {
newNo = "1";
} else {
Integer maxNo = Integer.parseInt(oldCode.substring(oldCode.length() - noLen));
newNo = String.valueOf(maxNo + 1);
}
int length = newNo.length();
if(length > noLen){
System.out.println("新流水號位數超限");
}
for (int i = 0; i < noLen - length; i++) {
newNo = "0".concat(newNo);
}
newCode = pre + currentDate + newNo;
CodeTest codeTest = new CodeTest();
codeTest.setCode(newCode);
codeTestDao.saveSelective(codeTest);
} finally {
lock.unlock();
}
System.out.println("生成的編碼為:"+newCode);
}
三、運行效果
1、將 db 文件夾下的 test.sql 導入數據庫
2、修改 jdbc.properties 文件中 mysql 連接
3、執行 CodeJunitTest 類下的 兩個測試方法

