文章目录
前言
各位新人请注意,在真实的生产环境中,购物车模块往往比网上教的复杂得多,以下只是简单地实现一些基本功能,业务量决定技术实现!
一.购物车
购物车在日常生活中十分常见,加入购物车、移出购物车、查看购物车…通过OOP的角度来看这就是一些CRUD,但值得注意的是,这不是简单的CRUD。首先,每一个用户的购物车是不同的,其次在现实生活中添加进去的商品不仅仅涉及到的是一张表(一类实体),比如我已经添加了选中的菜品(dish表),我还想添加套餐(套餐表)…这就不是一个简单的save方法能解决的
但是,只要静下心来理清表的结构,实体的联系,知道购物车对应表的字段是干什么的,是来操作什么关联表的,就会简单很多,先来看一下表的结构:
框起来的三个id格外的亮眼,在实现方法里就是通过id查到表对应的实体信息,然后对实体的属性进行操作,最后保存到各自对应的表中。
所谓的多表在代码实现过程中,其实就是几个表对应的Service之间调用方法来保存针对场景设置的属性值,记住这句话来看下面的代码就会变得非常简单!
@PostMapping("/add")publicR<ShoppingCart>add(@RequestBodyShoppingCart shoppingCart){
log.info("购物车信息:{}", shoppingCart.toString());//设置用户id,指定是当前是哪个用户的购物车Long currentId =BaseContext.getCurrentId();
shoppingCart.setUserId(currentId);LambdaQueryWrapper<ShoppingCart> shoppingCartLqw =newLambdaQueryWrapper<>();
shoppingCartLqw.eq(ShoppingCart::getUserId, currentId);//查找用户//查询当前菜品或者套餐是否在购物车中Long dishId = shoppingCart.getDishId();if(dishId !=null){//添加到购物车的是菜品
shoppingCartLqw.eq(ShoppingCart::getDishId, dishId);}else{//添加到购物车的是套餐
shoppingCartLqw.eq(ShoppingCart::getSetmealId, shoppingCart.getSetmealId());}ShoppingCart shopOne = shoppingCartService.getOne(shoppingCartLqw);if(shopOne !=null){//如果已在购物车中则菜品数量+1Integer num = shopOne.getNumber();
shopOne.setNumber(num +1);
shopOne.setCreateTime(LocalDateTime.now());
shoppingCartService.updateById(shopOne);}else{//如果不在购物车中则加入购物车,且数量默认为1
shoppingCart.setNumber(1);
shoppingCartService.save(shoppingCart);
shopOne = shoppingCart;}returnR.success(shopOne);}
看完这段代码,其实不难发现就是围绕着“拿实体,改实体”来做,只不过在实现的过程中需要注意一些小细节罢了。
下单关联表
经常网购都清楚,在下单前最重要的要素就是收货地址、用户基本信息(电话,身份证,姓名等等…)
在进行下单操作生成订单时都需要同时操作这几张表,把表里的信息读到订单表中。
在购物车的基础之上,用户下单就是对购物车对应表中的数据进行进一步操作,只不过下单的过程不仅仅涉及到购物车对应的表,还包括(用户地址,个人信息等等…),又是一次涉及到多表的操作。
二.用户下单
这次以订单表来保存用户基本信息Order,以订单明细表保存所选菜品信息OrderDetails,简单的购物车实现逻辑如图所示:
当点击下单,前端会发送过来一个请求(包含一些其他关联表的id):
对于后端,需要通过Order类型的实体接收,并通过其中已经封装的各种表id来操作其他表,就像这样:
@Transactionalpublicvoidsubmit(Orders orders){//获得当前用户idLong currentId =BaseContext.getCurrentId();LambdaQueryWrapper<ShoppingCart> shopLqw =newLambdaQueryWrapper<>();
shopLqw.eq(ShoppingCart::getUserId, currentId);//查询当前用户购物车数据List<ShoppingCart> shopOne = shoppingCartService.list(shopLqw);if(shopOne ==null|| shopOne.size()==0){thrownewCustomException("购物车为空,不能下单~");}//查询用户信息User userNow = userService.getById(currentId);//查询地址信息Long addressBookId = orders.getAddressBookId();AddressBook addressBook = addressBookService.getById(addressBookId);if(addressBook ==null){thrownewCustomException("不好意思,您还没有填写地址哟");}long orderId =IdWorker.getId();//订单号AtomicInteger amount =newAtomicInteger();//确保在多线程的情况下保证线程安全//向订单明细表中添加购物车中的内容(主要是餐品信息)List<OrderDetail> orderDetails = shopOne.stream().map((item)->{OrderDetail orderDetail =newOrderDetail();
orderDetail.setOrderId(orderId);
orderDetail.setNumber(item.getNumber());
orderDetail.setDishFlavor(item.getDishFlavor());
orderDetail.setDishId(item.getDishId());
orderDetail.setSetmealId(item.getSetmealId());
orderDetail.setName(item.getName());
orderDetail.setImage(item.getImage());
orderDetail.setAmount(item.getAmount());
amount.addAndGet(item.getAmount().multiply(newBigDecimal(item.getNumber())).intValue());return orderDetail;}).collect(Collectors.toList());//向订单表中添加基本信息(用户基本信息)
orders.setId(orderId);
orders.setOrderTime(LocalDateTime.now());
orders.setCheckoutTime(LocalDateTime.now());
orders.setStatus(2);
orders.setAmount(newBigDecimal(amount.get()));
orders.setUserId(currentId);
orders.setNumber(String.valueOf(orderId));
orders.setUserName(userNow.getName());
orders.setConsignee(addressBook.getConsignee());
orders.setPhone(addressBook.getPhone());
orders.setAddress((addressBook.getProvinceName()==null?"": addressBook.getProvinceName())+(addressBook.getCityName()==null?"": addressBook.getCityName())+(addressBook.getDistrictName()==null?"": addressBook.getDistrictName())+(addressBook.getDetail()==null?"": addressBook.getDetail()));//向订单插入一条数据,主要是客户基本信息this.save(orders);//向订单明细表插入多条数据,主要是客户所选餐品
orderDetailService.saveBatch(orderDetails);//清空购物车数据
shoppingCartService.remove(shopLqw);}
在实现过程中有一些细节还是值得注意一下:
1.涉及多表要开启事务,确保一致性
2.new AtomicInteger()来定义餐品数量,确保线程安全
3.全局异常要处理好
4.当完成了生成订单之后要记得清空购物车
购物车与订单的关系
在这之前,我总是不能深刻理解购物车与订单之间的关系,实现下单功能后才逐渐明了,原来订单是购物车的载体,购物车的出现就是为了生成订单而服务的,购物车包含于订单!
版权归原作者 懒羊羊.java 所有, 如有侵权,请联系我们删除。