Java如何生成序列號(hào)/訂單號(hào)

今天給大家?guī)?lái)也是比較實(shí)用的功能,用Java來(lái)生成序列號(hào)/訂單號(hào),列舉幾個(gè)在我們生活中比較常見的案例:
訂單號(hào)
商品編號(hào)
交易單號(hào)
快遞單號(hào)
數(shù)據(jù)存儲(chǔ)我是使用的?mysql,下面就向大家分享一下是如何實(shí)現(xiàn)的~
理論知識(shí)
什么是事務(wù)?
數(shù)據(jù)庫(kù)事務(wù)(簡(jiǎn)稱:事務(wù))是數(shù)據(jù)庫(kù)管理系統(tǒng)執(zhí)行過程中的一個(gè)邏輯單位,由一個(gè)有限的數(shù)據(jù)庫(kù)操作序列構(gòu)成。
臟讀、不可重復(fù)讀、幻讀
1、臟讀:A 事務(wù)對(duì)數(shù)據(jù)修改但還沒有提交到數(shù)據(jù)庫(kù),這個(gè)時(shí)候 B 事務(wù)來(lái)訪問,那么 B 事務(wù)對(duì)數(shù)據(jù)就不是最新的,這種現(xiàn)象被成為臟讀。
2、不可重復(fù)讀:A 事務(wù)多次讀取一個(gè)數(shù)據(jù),這個(gè)時(shí)候在中途 B 事務(wù)修改了數(shù)據(jù),導(dǎo)致 A 事務(wù)多次讀到的結(jié)果不一致。
3、幻讀:A 事務(wù)在前后兩次查詢同一個(gè)范圍的時(shí)候、后一次查詢看到了前一次查詢未看到的行,因?yàn)?B 事務(wù)在后一次查詢前新增加了一條數(shù)據(jù)。
mysql 的四種隔離級(jí)別
按照隔離的級(jí)別由低到高,越高的隔離,效率越差,不可重復(fù)讀,是 MySQL 的默認(rèn)隔離級(jí)別。

1、讀未提交:允許別的事務(wù),去讀取這個(gè)事務(wù)為提交之前的數(shù)據(jù) 缺點(diǎn):可能會(huì)造成臟讀、幻讀、不可重復(fù)讀。
2、不可重復(fù)讀:并發(fā)條件下會(huì)出現(xiàn)問題,比如:A 用戶讀取數(shù)據(jù), 隨后 B 用戶讀出該數(shù)據(jù)并修改, 此時(shí) A 用戶再讀取數(shù)據(jù)時(shí)發(fā)現(xiàn)前后兩次的值不一致 缺點(diǎn):可能會(huì)造成幻讀、不可重復(fù)讀。
3、可重復(fù)讀:當(dāng)使用可重復(fù)讀隔離級(jí)別時(shí),在事務(wù)執(zhí)行期間會(huì)鎖定該事務(wù)以任何方式引用的所有行。缺點(diǎn):幻讀
4、串行化:不會(huì)使用 mysql 的 mvcc 機(jī)制,在每一個(gè) select 請(qǐng)求下獲得讀鎖,在每一個(gè) update 操作下嘗試獲得寫鎖。缺點(diǎn):效率最差
兩種悲觀鎖
共享鎖 (S 鎖): 如果事務(wù) T 對(duì)數(shù)據(jù) A 加上共享鎖后,則其他事務(wù)只能對(duì) A 再加共享鎖,不能加排他鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。
排它鎖 (X 鎖):如果事務(wù) T 對(duì)數(shù)據(jù) A 加上排他鎖后,則其他事務(wù)不能再對(duì) A 加任任何類型的封鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。
Java 代碼實(shí)現(xiàn)
private String createNewBidNumber() {
//格式說(shuō)明 CODE20201111xxx CODE+當(dāng)前年月日+編號(hào)(具體長(zhǎng)度看需求)
String front="CODE";//前綴
//當(dāng)前時(shí)間編碼
Date date = new Date();
String bidDate = new SimpleDateFormat("yyyyMMdd").format(date);
Object bidService=null;//修改為自己的業(yè)務(wù)代碼
if (bidService != null){// 在數(shù)據(jù)表中查到了,說(shuō)明現(xiàn)在這個(gè)訂單不是今天的第一單
String bid = bidService.getXXXX(); //取出ID,也就是業(yè)務(wù)號(hào)
bid = bid.substring(10,13); // 取出后三位數(shù),也就是自動(dòng)生成的三位數(shù) 001
int num = Integer.valueOf(bid);
num ++; // 加1
if(num<10){
String bidNum = String.format("%03d", num);//%03d 只是三位,不足補(bǔ)0
String code = front+bidDate+bidNum;
return code;
}
else if(num<100){
String bidNum = String.format("%03d", num);//num<100,說(shuō)明是兩位數(shù),前面要補(bǔ)一個(gè)0
String code = front+bidDate+bidNum;
return code;
}
else {
String bidNum = String.valueOf(num);
String code =front+bidDate+bidNum;
return code;
}
}else {
int number = 1;
String bidNum = "00" + number;
String code = front+bidDate+bidNum;
return code;
}
}
歡迎關(guān)注“Java引導(dǎo)者”,我們分享最有價(jià)值的Java的干貨文章,助力您成為有思想的Java開發(fā)工程師!
