java+mysql實現(xiàn)商品搶購功能
我們希望有人購買時檢查商品數(shù)量是否足夠,如果庫存有剩余那么就讓用戶購買成功,之后變更庫存,假如用戶排隊挨個購買這樣當(dāng)然沒有問題。
可是實際情況下,可能是用戶多個用戶同時來購買,同時檢查庫存,這是可能庫存僅夠其中一人購買,但是由于庫存還沒減掉,就會出現(xiàn)幾個人都購買成功,然后庫存減為負數(shù)出現(xiàn)超賣的情況。這在大量用戶在同一時間點同時購買時極可能出現(xiàn)。
于是我們調(diào)整一下順序,有用戶購買時我們先減掉庫存,那你肯定要問,怎么減?庫存不夠一個人的時候也減?
我們假設(shè)每份商品有一個唯一的購買碼(開始搶購前預(yù)先生成),用戶搶到購買碼的數(shù)量即他買到的份數(shù),那么有用戶購買時我們第一步就是給幸運碼的狀態(tài)由有效更改為無效,并為其標(biāo)記上其購買者ID
這樣其實mysql會給我們一個返回結(jié)果,叫做影響行數(shù),就是說這條語句更新影響了多少行的數(shù)據(jù),這個影響行數(shù)就是他實際購買到的商品份數(shù),如果影響行數(shù)為0,就說明一份也沒購買成功,也就意味著商品已經(jīng)搶購?fù)瓿闪恕?/p>
java實現(xiàn):
/**
* 生成商品的購買碼<大量數(shù)據(jù)插入>
*
* @param goodsIssue
* @author Nifury
*/
public void insertLotteryNumbers(GoodsIssue goodsIssue) {
String prefix = "INSERT INTO `lottery_number` (`goods_id`, `periods`,`luck_number`, `create_time`, `status`, `issue_id` ) VALUES \n";
Timestamp now = new Timestamp(System.currentTimeMillis());
Connection con = null;
try {
con = jdbcTemplate.getDataSource().getConnection();
con.setAutoCommit(false);
PreparedStatement pst = con.prepareStatement("");
Long total = goodsIssue.getTotalShare();// 總?cè)舜?
for (int i = 0; i < total; i += 10000) {// 1萬條提交一次
StringBuffer suffix = new StringBuffer();
List<Integer> numbers = new ArrayList<Integer>();
for (int j = 0; j < 10000 && i+j < total; j++) {
numbers.add(10000001 + i + j);
}
Collections.shuffle(numbers);//打亂幸運碼
for (int n = 0,length = numbers.size(); n < length; n++) {
suffix.append("(" + goodsIssue.getGoodsId() + ","
+ goodsIssue.getPeriods() + ","
+ numbers.get(n) + ",'" + now.toString() + "',"
+ 1 + "," + goodsIssue.getIssueId() + ")\n,");
}
// 構(gòu)建完整sql
String sql = prefix + suffix.substring(0, suffix.length() - 2);
pst.addBatch(sql);
pst.executeBatch();
con.commit();
}
con.setAutoCommit(true);// 還原
pst.close();
con.close();
} catch (Exception e) {
e.printStackTrace();
try {// 事務(wù)回滾
con.rollback();
con.setAutoCommit(true);
con.close();
} catch (SQLException e1) {
e1.printStackTrace();
}// 還原
}
}
分配購買碼(我們的業(yè)務(wù)需要給購買用戶展示購買碼,所以有返回)
/**
* 通過商品issue_id(每期每個商品有唯一issue_id)來隨機獲取購買碼(使用的購買碼會設(shè)為失效狀態(tài))
* @param issueId
* @param amount 需要獲取的購買碼的數(shù)量
* @param userId
* @return LotteryNumber對象列表
* @author Nifury 2016-7-22
*/
public List<LotteryNumber> queryByNewIssueId2(Long issueId, Long amount,Long userId) {
List<LotteryNumber> numberList = new ArrayList<LotteryNumber>();
try {
long currentTime=System.currentTimeMillis();
String updateUserId = "UPDATE `lottery_number` SET `status` = 0,`user_id` = ?,`current_time`= ? WHERE `issue_id` = ? AND `status`=1 LIMIT ? ";
int rownum=jdbcTemplate.update(updateUserId, userId, currentTime, issueId, amount );
if(rownum>0){//還有剩余有效購買碼
Object[] buyargs={issueId, userId ,currentTime};
numberList = jdbcTemplate.query(QUERY + " WHERE `issue_id` = ? AND `status` = 0 AND `user_id` = ? AND `current_time`= ?",
buyargs, LotteryNumberMapper);
}
} catch (DeadlockLoserDataAccessException e) {
System.out.println("----分配購買碼出現(xiàn)死鎖,用戶分得0個購買碼-----");
}
return numberList;
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java關(guān)鍵字詳解之final static this super的用法
this用來調(diào)用目前類自身的成員變量,super多用來調(diào)用父類的成員,final多用來定義常量用的,static定義靜態(tài)變量方法用的,靜態(tài)變量方法只能被類本身調(diào)用,下文將詳細介紹,需要的朋友可以參考下2021-10-10
使用Maven 搭建 Spring MVC 本地部署Tomcat的詳細教程
這篇文章主要介紹了使用Maven 搭建 Spring MVC 本地部署Tomcat,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
解析MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件
在項目中用到了MapStruct,對其可以轉(zhuǎn)換JavaBean特別好奇,今天小編給大家分享一個demo給大家講解MapStruct轉(zhuǎn)換javaBean時出現(xiàn)的詭異事件,感興趣的朋友一起看看吧2021-09-09
MyBatis之自查詢使用遞歸實現(xiàn) N級聯(lián)動效果(兩種實現(xiàn)方式)
這篇文章主要介紹了MyBatis之自查詢使用遞歸實現(xiàn) N級聯(lián)動效果,本文給大家分享兩種實現(xiàn)方式,需要的的朋友參考下吧2017-07-07
Java的Cglib動態(tài)代理實現(xiàn)方式詳解
這篇文章主要介紹了Java的Cglib動態(tài)代理實現(xiàn)方式詳解,CGLIB是強大的、高性能的代碼生成庫,被廣泛應(yīng)用于AOP框架,它底層使用ASM來操作字節(jié)碼生成新的類,為對象引入間接級別,以控制對象的訪問,需要的朋友可以參考下2023-11-11
SSM使用mybatis分頁插件pagehepler實現(xiàn)分頁示例
本篇文章主要介紹了SSM使用mybatis分頁插件pagehepler實現(xiàn)分頁示例,使用分頁插件的原因,簡化了sql代碼的寫法,實現(xiàn)較好的物理分頁,非常具有實用價值,需要的朋友可以參考下2018-03-03
Mybatis批量修改聯(lián)合主鍵數(shù)據(jù)的兩種方法
最近遇上需要批量修改有聯(lián)合主鍵的表數(shù)據(jù),找很多資料都不是太合適,最終自己摸索總結(jié)了兩種方式可以批量修改數(shù)據(jù),對Mybatis批量修改數(shù)據(jù)相關(guān)知識感興趣的朋友一起看看吧2022-04-04
Spring?Security?基于URL的權(quán)限判斷源碼解析
這篇文章主要介紹了Spring?Security?基于URL的權(quán)限判斷問題,我們想要實現(xiàn)自己的基于請求Url的授權(quán)只需自定義一個?AccessDecisionManager即可,接下來跟隨小編一起看看實現(xiàn)代碼吧2021-12-12

