购物车操作
添加购物车:
需求分析和接口设计:
-
接口设计:
-
请求方式:POST
- 请求路径:/user/shoppingCart/add
- 请求参数:套餐id、菜品id、口味
- 返回结果:code、data、msg
数据库设计:
这上面出现了一些冗余字段。
这些冗余字段出现的原因是:
我们仔细观察这张图,当我们点开购物车的时候,我们需要知道这个套餐或者这个菜品的名称和图片,我们可以在加入数据的时候,将这些数据加入,这样就可以避免我们既要查找购物车这张表,然后又要取数据库中查询对应的名称和图片,提高效率,不过这也是一种空间换时间的做法,冗余字段不宜过多
添加购物车具体代码实现:
Controller层:
/*** 添加购物车* @param shoppingCartDTO* @return*/@PostMapping("/add")@ApiOperation("添加购物车")public Result insert(@RequestBody ShoppingCartDTO shoppingCartDTO){log.info("添加购物车:{}",shoppingCartDTO);shoppingCartService.add(shoppingCartDTO);return Result.success();}
Service层:
/*** 添加购物车* @param shoppingCartDTO* @return*/@Overridepublic void add(ShoppingCartDTO shoppingCartDTO) {//判断当前加入到购物车的商品是否已经存在了ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);Long userId = BaseContext.getCurrentId();shoppingCart.setUserId(userId);List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);//如果存在,直接数量加 1 (update)if(!list.isEmpty()){ShoppingCart cart = list.get(0);cart.setNumber(cart.getNumber()+1);shoppingCartMapper.updateById(cart);}else {//如果不存在在插入一条购物车数据(insert)//不存在的情况下,我们也是需要取判断传进来的是套餐还是菜品Long dishId = shoppingCart.getDishId();if(dishId!=null){//dishId不等于0,说明传进来的是一个菜品//传进来的是一个菜品,我们需要取设置这个菜品的值System.out.println(dishId);Dish dish = dishMapper.selectById(dishId);shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shoppingCart.setAmount(dish.getPrice());}else{//说明不是菜品,是套餐Long setmealId = shoppingCart.getSetmealId();Setmeal setmeal = setmealMapper.getById(setmealId);shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shoppingCart.setAmount(setmeal.getPrice());}shoppingCart.setNumber(1);shoppingCart.setCreateTime(LocalDateTime.now());shoppingCartMapper.insertById(shoppingCart);}}
添加购物车主要做了以下四步:
- 判断购物车中是否存在我们添加的商品或者套餐
- 如果存在,直接让数量+1(update)
- 如果不存在,再插入购物车(insert)
- 当我们插入的时候,我们还需要考虑插入的是菜品还是套餐。
注意点:
这里我们在判断购物车中是否有商品的时候,我们用了LocalThread中获取用户id的方法
这个道理很简单,我们不能把我们的商品添加到别人的购物车里去,
同时在下面的删除购物车的操作中,我们也用到了这个方法
结合之前写过的一些crud的操作,我发现我在新增员工的操作中也用了类似的方法
所以,可以总结,碰到用户或者是员工这种带有身份信息的情况的时候,可以采用LocalThread的方法来获取id。
Mapper层及注解:
/**** @param shoppingCart* @return*/List<ShoppingCart> list(ShoppingCart shoppingCart);/*** 如果商品存在,更新商品数量* @param cart*/@Update("update sky_take_out.shopping_cart set number = #{number} where id = #{id}")void updateById(ShoppingCart cart);@Insert("INSERT into sky_take_out.shopping_cart(name, image, user_id, dish_id, setmeal_id, dish_flavor, amount, create_time)" +"values " +"(#{name},#{image},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{amount},#{createTime})")void insertById(ShoppingCart shoppingCart);
<select id="list" resultType="com.sky.entity.ShoppingCart">select * from sky_take_out.shopping_cart<where><if test="userId != null">and user_id = #{userId}</if><if test="setmealId != null">and setmeal_id = #{setmealId}</if><if test="dishId != null">and dish_id = #{dishId}</if><if test="dishFlavor != null">and dish_flavor = #{dishFlavor}</if></where></select>
删除购物车:
具体代码实现:
Controller层:
/*** 删除购物车中的一个商品* @param shoppingCartDTO* @return*/@PostMapping("/sub")@ApiOperation("删除购物车中的一个商品")public Result subShoppingCart(@RequestBody ShoppingCartDTO shoppingCartDTO){log.info("删除购物车中的一个商品:{}",shoppingCartDTO);shoppingCartService.subShoppingCart(shoppingCartDTO);return Result.success();}
Service层:
/*** 删除购物车中的一个商品* @param shoppingCartDTO* @return*/@Overridepublic void subShoppingCart(ShoppingCartDTO shoppingCartDTO) {ShoppingCart shoppingCart = new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO,shoppingCart);//设置查询条件,查询当前登录用户的购物车数据Long userId = BaseContext.getCurrentId();shoppingCart.setUserId(userId);List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);shoppingCart = list.get(0);Integer number = shoppingCart.getNumber();System.out.println(number);//判断数量,如果>1,直接update -1即可if(number>1){shoppingCart.setNumber(shoppingCart.getNumber()-1);shoppingCartMapper.updateById(shoppingCart);}else {//如果数量只有一个,就执行删除操作shoppingCartMapper.deleteById(shoppingCart.getId());}}
这个删除购物车的思路总体和添加差不多,
就是先根据用户id获取对应的购物车数据。
然后判断数量,数量如果大于1,直接修改数据库中的操作就行
如果等于1,就删除就行。
Mapper层:
/*** 删除购物车中的一个商品* @param Id* @return*/@Delete("delete from sky_take_out.shopping_cart where id=#{Id}")void deleteById(Long Id);
下面的几个操作已经没有什么难点了,主要就是记录一下,
查看购物车:
/*** 查看购物车* @param* @return*/@GetMapping("/list")@ApiOperation("查看购物车")public Result<List<ShoppingCart>> list(){log.info("查看购物车");List<ShoppingCart> shoppingCartList = shoppingCartService.selectShoppingCart();return Result.success(shoppingCartList);}
/*** 查看购物车* @param* @return*/@Overridepublic List<ShoppingCart> selectShoppingCart() {final Long currentId = BaseContext.getCurrentId();ShoppingCart shoppingCart = ShoppingCart.builder().userId(currentId).build();final List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);return list;}
/**** @param shoppingCart* @return*/List<ShoppingCart> list(ShoppingCart shoppingCart);
清空购物车:
/*** 清空购物车* @return*/@DeleteMapping("/clean")@ApiOperation("清空购物车")public Result cleanShoppingCart(){log.info("清空购物车");shoppingCartService.cleanShoppingCart();return Result.success();}
/*** 清空购物车* @return*/@Overridepublic void cleanShoppingCart() {final Long currentId = BaseContext.getCurrentId();shoppingCartMapper.deleteAll(currentId);}
/*** 清空购物车* @return*/@Delete("delete from sky_take_out.shopping_cart where user_id = #{currentId}")void deleteAll(Long currentId);
相关文章:

购物车操作
添加购物车: 需求分析和接口设计: 接口设计: 请求方式:POST 请求路径:/user/shoppingCart/add请求参数:套餐id、菜品id、口味返回结果:code、data、msg 数据库设计: 这上面出现了…...

华为手机 鸿蒙系统-android studio识别调试设备,开启adb调试权限
1.进入设置-关于手机-版本号,连续点击7次 认证:有锁屏密码需要输入密码, 开启开发者配置功能ok 进入开发者配置界面 打开调试功能 重新在androd studio查看可运行running devices显示了, 不行的话,重启一下android …...

计算机网络——Dijkstra路由算法
实验目的 实现基于 Dijkstra 算法的路由软件 实验内容 网络拓扑如图所示 实验过程 先编写开辟应该图的空间,然后给点映射数字,构建图。程序获取用户输入的学号,构建图中边的权值。接下来程序从用户输入获取最短路径的搜索起点࿰…...

AI智能化逐渐趋于成熟后,预测今后最吃香的开发职业
AI智能化正在成熟的路途中,这中间会有波折,但终有一天会来的,我相信等到了这一天,我们的开发效率和代码质量,将会大大不同,而我们的团队与个人,也会面临着很棒的体验。 那么在AI智能化真正趋于成…...
Acwing2024蓝桥杯BFS
AcWing 1355. 母亲的牛奶 bfs: #include<iostream> #include<queue> using namespace std; const int N21; int A,B,C; bool flag[N][N][N]; struct node{int a,b,c; }; queue<node>q; void check(int a,int b,int c){if(!flag[a][b][c]){q.push({a,b,c})…...

vue打包报错:CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
前言: vue项目,打包报错:CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 报错现象: 报错原因: 这个错误是由Node.js在尝试分配内存时因为系统的可用内存不足而发生的。"JavaScript heap…...

计算机组成原理网课笔记
无符号整数的表示与运算 带符号整数的表示与运算 原反补码的特性对比 移码 定点小数...
Python学习第四部分 函数式编程
文章目录 高阶函数lambda 表达式和匿名函数偏函数闭包map函数reduce函数filter 函数sorted函数 函数式编程主要学习:高阶函数、闭包closure、匿名函数、偏函数,map函数、reduce函数、filter函数、sorted函数 函数式编程是个很古老的概念,最古…...

数据结构-二叉树-AVL树(平衡二叉树)
红黑树是平衡二叉树的一个变种。 一、 产生平衡二叉树的原因。 二叉搜索树的问题在于极端场景下退化为类似链表的结构,所以搜索的时间复杂度就变成了O(N)。为了保证二叉树不退化为链表,我们必须保证二叉树的的平衡性。 二叉平衡搜索树就是解决上面的问…...

【Qt问题】windeployqt如何提取Qt依赖库
往期回顾 【Qt问题】Qt Creator 如何链接第三方库-CSDN博客 【Qt问题】Qt 如何带参数启动外部进程-CSDN博客 【Qt问题】VS2019 Qt win32项目如何添加x64编译方式-CSDN博客 【Qt问题】windeployqt如何提取Qt依赖库 考虑这个问题主要是:当我们的程序运行好之后&#…...

VS2019下使用MFC完成科技项目管理系统
背景: (一)实验目的 通过该实验,使学生掌握windows程序设计的基本方法。了解科技项目组织管理的主要内容和管理方面的基本常识,熟练应用数据库知识,通过处理过程对计算机软件系统工作原理的进一步理解&…...

【Android】Kotlin学习之数据容器(数组for循环遍历)
数组遍历 1. for ( item in arr){…} 2. for ( i in arr.indeces ) {…} (遍历下标) 3. for ((index, item) in arr.withInfex()) {…} (遍历下标和元素) 4. arr.forEach {} ( 遍历元素 ) 5. arr.forEachIndexed{index, item -> …}...

JavaWeb_请求响应_简单参数实体参数
一、SpringBoot方式接收携带简单参数的请求 简单参数:参数名与形参变量名相同,定义形参即可接收参数。并且在接收过程中,会进行自动的类型转换。 启动应用程序后,在postman中进行测试: 请求成功,响应回了O…...

windows端口复用
1. 概述 使用 HTTP.sys 中的 Net.tcp Port Sharing 服务,配合 WinRM 实现端口复用。 优点: HTTP.sys 为 windows 原生机制, WinRM 为 windows 自带功能,动作较小,不易触发主 动防御。 需要管理员权限。 2. 原理 (…...

[Redis] 使用布隆过滤器和分布式锁实现用户注册
布隆过滤器(Bloom Filter)是一种数据结构,用于快速判断一个元素是否可能存在于一个集合中。它通过使用多个哈希函数和一个位数组来表示一个集合,当一个元素被加入到集合时,通过哈希函数计算出多个哈希值,并…...
Okhttp 发送https请求,忽略ssl认证
工具类 import lombok.extern.slf4j.Slf4j;import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509Tru…...

IT项目管理-大题【太原理工大学】
一、根据进度网络写出时间参数表、关键路径、总工期 此类题一般是给一个表,问三问。 第一问会问某个活动的时间参数,但我们需要把整个表都求出来,否则单求一个很困难(如果你就是不想求整张表也行,不是硬性要求…...
【代码随想录】day48
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一、198打家劫舍二、213打家劫舍II三、337打家劫舍III 一、198打家劫舍 class Solution { public:int rob(vector<int>& nums) {vector<int> dp(n…...
【补充】1-auth的使用、扩写auth的user表、django支持缓存
1 Auth的使用 1.1 扩写auth的user表 2 缓存 1 Auth的使用 # django 的一个app---》用户的登录,退出,注册。。。# 配置文件中配置:---》表会被迁移INSTALLED_APPS [django.contrib.auth,]# auth有哪些表---权限控制:-Permission&a…...

力扣-21. 合并两个有序链表-js实现
/*** Definition for singly-linked list.* function ListNode(val, next) {* this.val (valundefined ? 0 : val)* this.next (nextundefined ? null : next)* }*/ /*** param {ListNode} list1* param {ListNode} list2* return {ListNode}*/ const mergeTwoList…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
CSS设置元素的宽度根据其内容自动调整
width: fit-content 是 CSS 中的一个属性值,用于设置元素的宽度根据其内容自动调整,确保宽度刚好容纳内容而不会超出。 效果对比 默认情况(width: auto): 块级元素(如 <div>)会占满父容器…...

【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...

零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...
数据库正常,但后端收不到数据原因及解决
从代码和日志来看,后端SQL查询确实返回了数据,但最终user对象却为null。这表明查询结果没有正确映射到User对象上。 在前后端分离,并且ai辅助开发的时候,很容易出现前后端变量名不一致情况,还不报错,只是单…...

【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...