這篇文章主要為大家展示了“java+MySQL中怎么實(shí)現(xiàn)商品搶購(gòu)功能”,內(nèi)容簡(jiǎn)而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“java+mysql中怎么實(shí)現(xiàn)商品搶購(gòu)功能”這篇文章吧。
創(chuàng)新互聯(lián)建站2013年開創(chuàng)至今,先為句容等服務(wù)建站,句容等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢服務(wù)。為句容企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問題。
我們希望有人購(gòu)買時(shí)檢查商品數(shù)量是否足夠,如果庫(kù)存有剩余那么就讓用戶購(gòu)買成功,之后變更庫(kù)存,假如用戶排隊(duì)挨個(gè)購(gòu)買這樣當(dāng)然沒有問題。
可是實(shí)際情況下,可能是用戶多個(gè)用戶同時(shí)來購(gòu)買,同時(shí)檢查庫(kù)存,這是可能庫(kù)存僅夠其中一人購(gòu)買,但是由于庫(kù)存還沒減掉,就會(huì)出現(xiàn)幾個(gè)人都購(gòu)買成功,然后庫(kù)存減為負(fù)數(shù)出現(xiàn)超賣的情況。這在大量用戶在同一時(shí)間點(diǎn)同時(shí)購(gòu)買時(shí)極可能出現(xiàn)。
于是我們調(diào)整一下順序,有用戶購(gòu)買時(shí)我們先減掉庫(kù)存,那你肯定要問,怎么減?庫(kù)存不夠一個(gè)人的時(shí)候也減?
我們假設(shè)每份商品有一個(gè)唯一的購(gòu)買碼(開始搶購(gòu)前預(yù)先生成),用戶搶到購(gòu)買碼的數(shù)量即他買到的份數(shù),那么有用戶購(gòu)買時(shí)我們第一步就是給幸運(yùn)碼的狀態(tài)由有效更改為無效,并為其標(biāo)記上其購(gòu)買者ID
"UPDATE `lottery_number` SET `status` = 失效狀態(tài),`user_id` = 購(gòu)買者用戶Id,`current_time`= 時(shí)間戳 WHERE `goods_id` = 搶購(gòu)的商品ID AND `status`=有效狀態(tài) LIMIT 購(gòu)買份數(shù) ";
這樣其實(shí)mysql會(huì)給我們一個(gè)返回結(jié)果,叫做影響行數(shù),就是說這條語(yǔ)句更新影響了多少行的數(shù)據(jù),這個(gè)影響行數(shù)就是他實(shí)際購(gòu)買到的商品份數(shù),如果影響行數(shù)為0,就說明一份也沒購(gòu)買成功,也就意味著商品已經(jīng)搶購(gòu)?fù)瓿闪恕?/p>
java實(shí)現(xiàn):
/** * 生成商品的購(gòu)買碼<大量數(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(); Listnumbers = new ArrayList (); for (int j = 0; j < 10000 && i+j < total; j++) { numbers.add(10000001 + i + j); } Collections.shuffle(numbers);//打亂幸運(yùn)碼 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(); }// 還原 } }
分配購(gòu)買碼(我們的業(yè)務(wù)需要給購(gòu)買用戶展示購(gòu)買碼,所以有返回)
/** * 通過商品issue_id(每期每個(gè)商品有唯一issue_id)來隨機(jī)獲取購(gòu)買碼(使用的購(gòu)買碼會(huì)設(shè)為失效狀態(tài)) * @param issueId * @param amount 需要獲取的購(gòu)買碼的數(shù)量 * @param userId * @return LotteryNumber對(duì)象列表 * @author Nifury 2016-7-22 */ public ListqueryByNewIssueId2(Long issueId, Long amount,Long userId) { List numberList = new ArrayList (); 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){//還有剩余有效購(gòu)買碼 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("----分配購(gòu)買碼出現(xiàn)死鎖,用戶分得0個(gè)購(gòu)買碼-----"); } return numberList; }
以上是“java+mysql中怎么實(shí)現(xiàn)商品搶購(gòu)功能”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!