java+mysql商品の買い占め機能を実現します。
購入時に商品の数量が十分かどうかを確認したいです。在庫が残ったら、ユーザーに購入させて成功させます。その後、在庫を変更します。もしユーザが順番に並んで買うなら、もちろん大丈夫です。
しかし、実際の状況では、複数のユーザーが同時に購入し、在庫を確認することができます。これは在庫が一人しかないかもしれません。しかし、在庫がまだ減っていないため、何人かが購入に成功し、在庫がマイナスになって販売超過が発生します。これは多くのユーザーが同じ時点で同時に買う時に現れる可能性が高いです。
そこで私達は順番を調整して、ユーザーが買う時先に在庫を減らします。どうやって減らすべきですか?在庫が一人足りない時も減りますか?
私たちは商品ごとに唯一の購入コードがあると仮定します。(買い占めを始める前に予め生成しておきます。)ユーザーが購入コードの数である彼が買った分の数を奪ったら、ユーザーが購入する時の第一歩は幸運コードの状態に有効から無効に変更し、購入者IDをマークします。
java実装:
しかし、実際の状況では、複数のユーザーが同時に購入し、在庫を確認することができます。これは在庫が一人しかないかもしれません。しかし、在庫がまだ減っていないため、何人かが購入に成功し、在庫がマイナスになって販売超過が発生します。これは多くのユーザーが同じ時点で同時に買う時に現れる可能性が高いです。
そこで私達は順番を調整して、ユーザーが買う時先に在庫を減らします。どうやって減らすべきですか?在庫が一人足りない時も減りますか?
私たちは商品ごとに唯一の購入コードがあると仮定します。(買い占めを始める前に予め生成しておきます。)ユーザーが購入コードの数である彼が買った分の数を奪ったら、ユーザーが購入する時の第一歩は幸運コードの状態に有効から無効に変更し、購入者IDをマークします。
"UPDATE `lottery_number` SET `status` = ,`user_id` = Id,`current_time`= WHERE `goods_id` = ID AND `status`= LIMIT ";
このように実はmysqlは私達に1つの返却結果を与えてくれます。影響行数といいます。つまり、この文の更新は何行のデータに影響していますか?java実装:
/**
* < >
*
* @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
";
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();//
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() + ")
,");
}
// 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 {//
con.rollback();
con.setAutoCommit(true);
con.close();
} catch (SQLException e1) {
e1.printStackTrace();
}//
}
}
購入コードの割り当て(私たちの業務は購入者に購入コードを示す必要がありますので、返却があります。)
/**
* issue_id( issue_id) ( )
* @param issueId
* @param amount
* @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("---- , 0 -----");
}
return numberList;
}
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。