数据库设计
- 商品表
- 秒杀商品表
- 订单表
- 秒杀订单表
秒杀商品表要单独建立,而不能在商品表里面标记是不是秒杀商品
秒杀活动越来越多就很难维护
商品表
建立商品表,插入数据
CREATE TABLE `goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '商品ID',
`goods_name` varchar(16) DEFAULT NULL COMMENT '商品名称',
`goods_title` varchar(64) DEFAULT NULL COMMENT '商品标题',
`goods_img` varchar(64) DEFAULT NULL COMMENT '商品的图片',
`goods_detail` longtext COMMENT '商品的详情介绍',
`goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品单价',
`goods_stock` int(11) DEFAULT '0' COMMENT '商品库存,-1表示没有限制',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
还有对应的商品信息:
public class GoodsVo extends Goods{
private Double miaoshaPrice;
private Integer stockCount;
private Date startDate;
private Date endDate;
}
public class Goods {
private Long id;
private String goodsName;
private String goodsTitle;
private String goodsImg;
private String goodsDetail;
private Double goodsPrice;
private Integer goodsStock;
}
INSERT INTO `goods`
VALUES
(1,'iphoneX','Apple iPhone X (A1865) 64GB 银色 移动联通电信4G手机','/img/iphonex.png','Apple iPhone X (A1865) 64GB 银色 移动联通电信4G手机',8765.00,10000),
(2,'华为Meta9','华为 Mate 9 4GB+32GB版 月光银 移动联通电信4G手机 双卡双待','/img/meta10.png','华为 Mate 9 4GB+32GB版 月光银 移动联通电信4G手机 双卡双待',3212.00,-1);
秒杀商品表
建立秒杀商品表,插入数据
CREATE TABLE `miaosha_goods` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '秒杀的商品表',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品Id',
`miaosha_price` decimal(10,2) DEFAULT '0.00' COMMENT '秒杀价',
`stock_count` int(11) DEFAULT NULL COMMENT '库存数量',
`start_date` datetime DEFAULT NULL COMMENT '秒杀开始时间',
`end_date` datetime DEFAULT NULL COMMENT '秒杀结束时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
public class MiaoshaGoods {
private Long id;
private Long goodsId;
private Integer stockCount;
private Date startDate;
private Date endDate;
}
INSERT INTO `miaosha_goods`
VALUES
(1,1,0.01,4,'2017-11-05 15:18:00','2017-11-13 14:00:18'),
(2,2,0.01,9,'2017-11-12 14:00:14','2017-11-13 14:00:24');
订单表
public class OrderInfo {
private Long id;
private Long userId;
private Long goodsId;
private Long deliveryAddrId;
private String goodsName;
private Integer goodsCount;
private Double goodsPrice;
private Integer orderChannel;
private Integer status;
private Date createDate;
private Date payDate;
}
CREATE TABLE `order_info` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID',
`delivery_addr_id` bigint(20) DEFAULT NULL COMMENT '收获地址ID',
`goods_name` varchar(16) DEFAULT NULL COMMENT '冗余过来的商品名称',
`goods_count` int(11) DEFAULT '0' COMMENT '商品数量',
`goods_price` decimal(10,2) DEFAULT '0.00' COMMENT '商品单价',
`order_channel` tinyint(4) DEFAULT '0' COMMENT '1pc,2android,3ios',
`status` tinyint(4) DEFAULT '0' COMMENT '订单状态,0新建未支付,1已支付,2已发货,3已收货,4已退款,5已完成',
`create_date` datetime DEFAULT NULL COMMENT '订单的创建时间',
`pay_date` datetime DEFAULT NULL COMMENT '支付时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4;
秒杀订单表
public class MiaoshaOrder {
private Long id;
private Long userId;
private Long orderId;
private Long goodsId;
}
CREATE TABLE `miaosha_order` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
`order_id` bigint(20) DEFAULT NULL COMMENT '订单ID',
`goods_id` bigint(20) DEFAULT NULL COMMENT '商品ID',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
页面设计
商品列表页
<div class="panel panel-default">
<div class="panel-heading">秒杀商品列表</div>
<table class="table" id="goodslist">
<tr><td>商品名称</td><td>商品图片</td><td>商品原价</td><td>秒杀价</td><td>库存数量</td><td>详情</td></tr>
<tr th:each="goods,goodsStat : ${goodsList}">
<td th:text="${goods.goodsName}"></td>
<td ><img th:src="@{${goods.goodsImg}}" width="100" height="100" /></td>
<td th:text="${goods.goodsPrice}"></td>
<td th:text="${goods.miaoshaPrice}"></td>
<td th:text="${goods.stockCount}"></td>
<td><a th:href="'/goods/to_detail/'+${goods.id}">详情</a></td>
</tr>
</table>
</div>
商品详情页
<div class="panel panel-default">
<div class="panel-heading">秒杀商品详情</div>
<div class="panel-body">
<span> 您还没有登录,请登陆后再操作<br/></span>
<span>没有收货地址的提示。。。</span>
</div>
<table class="table" id="goodslist">
<tr>
<td>商品名称</td>
<td colspan="3"></td>
</tr>
<tr>
<td>商品图片</td>
<td colspan="3"><img th:src="" width="200" height="200" /></td>
</tr>
<tr>
<td>秒杀开始时间</td>
<td ></td>
<td id="miaoshaTip">
<span>秒杀已经结束</span>
</td>
<td>
<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
<button class="btn btn-primary btn-block" type="submit" id="buyButton">立即秒杀</button>
<input type="hidden" name="goodsId" th:value="${goods.id}" />
</form>
</td>
</tr>
<tr>
<td>商品原价</td>
<td colspan="3"></td>
</tr>
<tr>
<td>秒杀价</td>
<td colspan="3"></td>
</tr>
<tr>
<td>库存数量</td>
<td colspan="3"></td>
</tr>
</table>
</div>
订单详情页
<div class="panel panel-default">
<div class="panel-heading">秒杀商品详情</div>
<div class="panel-body">
<span> 您还没有登录,请登陆后再操作<br/></span>
<span>没有收货地址的提示。。。</span>
</div>
<table class="table" id="goodslist">
<tr>
<td>商品名称</td>
<td colspan="3"></td>
</tr>
<tr>
<td>商品图片</td>
<td colspan="3"><img th:src="" width="200" height="200" /></td>
</tr>
<tr>
<td>秒杀开始时间</td>
<td ></td>
<td id="miaoshaTip">
<span>秒杀已经结束</span>
</td>
<td>
<form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
<button class="btn btn-primary btn-block" type="submit" id="buyButton">立即秒杀</button>
<input type="hidden" name="goodsId" th:value="${goods.id}" />
</form>
</td>
</tr>
<tr>
<td>商品原价</td>
<td colspan="3"></td>
</tr>
<tr>
<td>秒杀价</td>
<td colspan="3"></td>
</tr>
<tr>
<td>库存数量</td>
<td colspan="3"></td>
</tr>
</table>
</div>
管理后台
domain中
创建这几个:
- Goods
- MiaoshaGoods
- OrderInfo
- MiaoshaOrder
Vo中
新创建这两个:
Dao中
new 这几个class
goodsDao{
@Update("update miaosha_goods set stock_count = stock_count -1 where goods_id = #{id}")
reduceStock(good)
}
orderDao{
@select("slect dddd")
getMiaoshaOrderByUserIdGoodId();
}
Service中
//GoodService
public GoodsVo getGoodsVoByGoodsId(long goodsId){
return goodsDao.getGoodsVoByGoodsId(goodsId);
}
@Service
public class OrderService {
@Autowired
OrderDao orderDao;
public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(long userId, long goodsId) {
return orderDao.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
}
@Transactional
public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
OrderInfo orderInfo = new OrderInfo();
orderInfo.setCreateDate(new Date());
orderInfo.setDeliveryAddrId(0L);
orderInfo.setGoodsCount(1);
orderInfo.setGoodsId(goods.getId());
orderInfo.setGoodsName(goods.getGoodsName());
orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
orderInfo.setOrderChannel(1);
orderInfo.setStatus(0);
orderInfo.setUserId(user.getId());
long orderId = orderDao.insert(orderInfo);
MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
miaoshaOrder.setGoodsId(goods.getId());
miaoshaOrder.setOrderId(orderId);
miaoshaOrder.setUserId(user.getId());
orderDao.insertMiaoshaOrder(miaoshaOrder);
return orderInfo;
}
}
miaoshaService{
goodsservice;
orderService;
@transanctional
public OrderInfo miaosha(MiaoshaUser user,GoodVo goods){
//减库存 下订单 写入秒杀订单
goodService.reduceStock(goods);
return orderService.createOrder(user,goods);
}
}
controller
@RequestMapping("/to_detail/{goodsId}")
public String detail(Model model,MiaoshaUser user,
@PathVariable("goodsId")long goodsId) {
model.addAttribute("user", user);
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
model.addAttribute("goods", goods);
long startAt = goods.getStartDate().getTime();
long endAt = goods.getEndDate().getTime();
long now = System.currentTimeMillis();
int miaoshaStatus = 0;
int remainSeconds = 0;
if(now < startAt ) {//秒杀还没开始,倒计时
miaoshaStatus = 0;
remainSeconds = (int)((startAt - now )/1000);
}else if(now > endAt){//秒杀已经结束
miaoshaStatus = 2;
remainSeconds = -1;
}else {//秒杀进行中
miaoshaStatus = 1;
remainSeconds = 0;
}
model.addAttribute("miaoshaStatus", miaoshaStatus);
model.addAttribute("remainSeconds", remainSeconds);
return "goods_detail";
}
@RequestMapping("/do_miaosha")
public String list(Model model,MiaoshaUser user,
@RequestParam("goodsId")long goodsId) {
model.addAttribute("user", user);
if(user == null) {
return "login";
}
//判断库存
GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
int stock = goods.getStockCount();
if(stock <= 0) {
model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
return "miaosha_fail";
}
//判断是否已经秒杀到了
MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
if(order != null) {
model.addAttribute("errmsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
return "miaosha_fail";
}
//减库存 下订单 写入秒杀订单
OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
model.addAttribute("orderInfo", orderInfo);
model.addAttribute("goods", goods);
return "order_detail";
}