秒杀商品(Java详解)-乐观锁

一群人抢购一件或者多件商品,让我们简单来模拟一下

首先数据库的准备:

因为是抢购商品所以需要商品表

CREATE TABLE `spd` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `shopFont` varchar(255) NOT NULL, -- 商品描述
  `shopPrice` int(11) NOT NULL, -- 商品价格
  `shopImg` varchar(255) NOT NULL, -- 商品图片
  `status` int(11) NOT NULL, -- 商品状态 1、普通出售 2、秒杀商品
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

添加数据:

INSERT INTO `spd` VALUES ('1', '苹果', '100', '图标', '1');
INSERT INTO `spd` VALUES ('2', '旺仔', '200', '图标', '0');

这是我们的商品表

然后在创建秒杀商品的表 : 由于我们是测试所以就不建表之间的关联了,由于有秒杀商品所以我们还需要建立一张秒杀商品的表

CREATE TABLE `spc` (
  `id` int(11) DEFAULT NULL,  -- 商品id
  `shopCount` int(11) DEFAULT NULL --库存
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

添加数据:

INSERT INTO `spc` VALUES ('1', '1');


因为有秒杀商品和普通商品所以查询展示的时候要关联查询

select * from spd insert into spc on spd.id=spc.id where spd.status=2; 

这样就可以查询出来所有的数据 然后返回给POJO里面的实体类中

然后可以把数据存入到Redis中替代Session 然后将数据展示到前端则可以看到了商品样式,当我们点击这个抢购的时候应该去跳转到后端http请求的方法中需要的值是点击的这个商品的id一块传入到后端

@RequestMapping("qianggou")
@ResponseBody
String shengcheng(Integer id) {

当我们接收到了这个商品的id下一步就可以去秒杀商品的表中查询库存是否大于0 如果大于0则就可以抢购

可以调用持久层的方法去通过id查询商品的信息返回到实体类中而拿到了这个实体类可以通过get方法去调用商品的库存是否大于0

Spc spc = spCMapper.selectId(id);
if (spc.getShopCount() > 0) {

  如果大于0则证明商品还未被抢完可以执行库存-1并且创建订单的操作

//        如果有则去商品库存-1
Integer integer = spCMapper.updateID(id);
<update id="updateID">
    update spc set shopCount=shopCount-1 where id=#{id} and shopCount>0
</update>

这是mybatis xml中的方法写法

update spc set :修改spc表

shopCount=shopCount-1: 商品的库存-1

where id=#{id} :

我们前端传过来的商品id是要秒杀哪一件商品所以需要一个确认值

and shopCount>0 :因为我们是多线程的操作 当一个线程进入了这个方法 另一个线程也进入了此方法 第一个线程去查询库存还剩1  第二个线程查询库存也还剩1 都剩下1的情况下两个线程又同时进入了商品大于1的方法 所以必须要有一个判断 当我们第一个线程先去执行了mybatis中的updateID方法 去把商品-1了 则库存中没有了数据  第二个方法进入updateID的时候 虽然也先去-1了 但是到了后面判断 条件的时候 shopCount已经被第一个线程去-1 等于了0 则0==0 !0>0 所以第二个线程不会执行-1的操作也不会创建订单了

接下来可以判断它们是否成功执行了mybatis中的方法并且返回了1 如果没返回1则应对了上面说的话,如果返回了1则为创建订单 

boolean falg=integer>0?true:false;

if(falg){

//可以进行创建订单 我们还需要一张订单表

CREATE TABLE `dingdan` (
  `id` varchar(255) DEFAULT NULL,
  `spid` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `status` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

然后通过刚才的数据可以直接进行添加到这个表中

return "添加成功订单!"; :然后可以返回

}else{

 如果没有添加成功则可以返回

return"订单已经被抢光!";

}

}

}else{
判断的是如果库存小于了0 证明没有库存了直接可以返回被抢光
return "订单已经被抢光!";
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java实现秒杀系统@Controller @RequestMapping("seckill")//url:/模块/资源/{id}/细分 /seckill/list public class SeckillController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillService seckillService; @RequestMapping(value="/list",method = RequestMethod.GET) public String list(Model model){ //获取列表页 List list=seckillService.getSeckillList(); model.addAttribute("list",list); //list.jsp+model = ModelAndView return "list";//WEB-INF/jsp/"list".jsp } @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET) public String detail(@PathVariable("seckillId") Long seckillId, Model model){ if (seckillId == null){ return "redirect:/seckill/list"; } Seckill seckill = seckillService.getById(seckillId); if (seckill == null){ return "forward:/seckill/list"; } model.addAttribute("seckill",seckill); return "detail"; } //ajax json @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) @ResponseBody public SeckillResult exposer(@PathVariable("seckillId") Long seckillId){ SeckillResult result; try { Exposer exposer =seckillService.exportSeckillUrl(seckillId); result = new SeckillResult(true,exposer); } catch (Exception e) { logger.error(e.getMessage(),e); result = new SeckillResult(false,e.getMessage()); } return result; } @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"} ) @ResponseBody public SeckillResult execute(@PathVariable("seckillId")Long seckillId,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值