网站建设上传文件,wordpress信息导出,昆明网站建设系统有哪些,北京公司注册官网苍穹外卖-day07 本项目学自黑马程序员的《苍穹外卖》项目#xff0c;是瑞吉外卖的Plus版本 功能更多#xff0c;更加丰富。 结合资料#xff0c;和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频#xff1a;https://www.bilibili.com/video/BV1TP411v7v6/?sp…苍穹外卖-day07 本项目学自黑马程序员的《苍穹外卖》项目是瑞吉外卖的Plus版本 功能更多更加丰富。 结合资料和自己对学习过程中的一些看法和问题解决情况上传课件笔记 视频https://www.bilibili.com/video/BV1TP411v7v6/?spm_id_from333.337.search-card.all.click 资料关注黑马程序员公众号----回复苍穹外卖 一起学习一起加油 【可以使用ApiFox代替YApi来导入的接口文档】 1、Redis缓存菜品以及SpringCache缓存套餐 文章目录 苍穹外卖-day071. 缓存菜品1.1 问题说明1.2 实现思路1.3 代码开发1.4 功能测试1.5 代码提交 2. 缓存套餐2.1 Spring Cache2.1.1 介绍2.1.2 常用注解2.1.3 入门案例 2.2 实现思路2.3 代码开发2.4 功能测试2.5 代码提交 3. 添加购物车3.1 需求分析和设计3.1.1 产品原型3.1.2 接口设计3.1.3 表设计 3.2 代码开发3.2.1 DTO设计3.2.2 Controller层3.2.3 Service层接口3.2.4 Service层实现类3.2.5 Mapper层 3.3 功能测试3.4 代码提交 4. 查看购物车4.1 需求分析和设计4.1.1 产品原型4.1.2 接口设计 4.2 代码开发4.2.1 Controller层4.2.2 Service层接口4.2.3 Service层实现类 4.3 功能测试4.4 代码提交 5. 清空购物车5.1 需求分析和设计5.1.1 产品原型5.1.2 接口设计 5.2 代码开发5.2.1 Controller层5.2.2 Service层接口5.2.3 Service层实现类5.2.4 Mapper层 5.3 功能测试5.4 代码提交 1. 缓存菜品
1.1 问题说明
用户端小程序展示的菜品数据都是通过查询数据库获得如果用户端访问量比较大数据库访问压力随之增大。 **结果**系统响应慢、用户体验差
1.2 实现思路
通过Redis来缓存菜品数据减少数据库查询操作。 缓存逻辑分析
每个分类下的菜品保存一份缓存数据数据库中菜品数据有变更时清理缓存数据 1.3 代码开发
修改用户端接口 DishController 的 list 方法加入缓存处理逻辑 Autowiredprivate RedisTemplate redisTemplate;/*** 根据分类id查询菜品** param categoryId* return*/GetMapping(/list)ApiOperation(根据分类id查询菜品)public ResultListDishVO list(Long categoryId) {//构造redis中的key规则dish_分类idString key dish_ categoryId;//查询redis中是否存在菜品数据ListDishVO list (ListDishVO) redisTemplate.opsForValue().get(key);if(list ! null list.size() 0){//如果存在直接返回无须查询数据库return Result.success(list);}Dish dish new Dish();dish.setCategoryId(categoryId);dish.setStatus(StatusConstant.ENABLE);//查询起售中的菜品//如果不存在查询数据库将查询到的数据放入redis中list dishService.listWithFlavor(dish);redisTemplate.opsForValue().set(key, list);return Result.success(list);}为了保证数据库和Redis中的数据保持一致修改管理端接口 DishController 的相关方法加入清理缓存逻辑。
需要改造的方法
新增菜品修改菜品批量删除菜品起售、停售菜品
抽取清理缓存的方法
在管理端DishController中添加 Autowiredprivate RedisTemplate redisTemplate;/*** 清理缓存数据* param pattern*/private void cleanCache(String pattern){Set keys redisTemplate.keys(pattern);redisTemplate.delete(keys);}调用清理缓存的方法保证数据一致性
1). 新增菜品优化 /*** 新增菜品** param dishDTO* return*/PostMappingApiOperation(新增菜品)public Result save(RequestBody DishDTO dishDTO) {log.info(新增菜品{}, dishDTO);dishService.saveWithFlavor(dishDTO);//清理缓存数据String key dish_ dishDTO.getCategoryId();cleanCache(key);return Result.success();}2). 菜品批量删除优化 /*** 菜品批量删除** param ids* return*/DeleteMappingApiOperation(菜品批量删除)public Result delete(RequestParam ListLong ids) {log.info(菜品批量删除{}, ids);dishService.deleteBatch(ids);//将所有的菜品缓存数据清理掉所有以dish_开头的keycleanCache(dish_*);return Result.success();}3). 修改菜品优化 /*** 修改菜品** param dishDTO* return*/PutMappingApiOperation(修改菜品)public Result update(RequestBody DishDTO dishDTO) {log.info(修改菜品{}, dishDTO);dishService.updateWithFlavor(dishDTO);//将所有的菜品缓存数据清理掉所有以dish_开头的keycleanCache(dish_*);return Result.success();}4). 菜品起售停售优化 /*** 菜品起售停售** param status* param id* return*/PostMapping(/status/{status})ApiOperation(菜品起售停售)public ResultString startOrStop(PathVariable Integer status, Long id) {dishService.startOrStop(status, id);//将所有的菜品缓存数据清理掉所有以dish_开头的keycleanCache(dish_*);return Result.success();}1.4 功能测试
可以通过如下方式进行测试
查看控制台sql前后端联调查看Redis中的缓存数据
以加入缓存、菜品修改两个功能测试为例通过前后端联调方式查看控制台sql的打印和Redis中的缓存数据变化。
1). 加入缓存
当第一次查询某个分类的菜品时会从数据为中进行查询同时将查询的结果存储到Redis中在后绪的访问若查询相同分类的菜品时直接从Redis缓存中查询不再查询数据库。
**登录小程序**选择蜀味牛蛙(id17) **查看控制台sql**有查询语句说明是从数据库中进行查询 **查看Redis中的缓存数据**说明缓存成功 **再次访问**选择蜀味牛蛙(id17) 说明是从Redis中查询的数据。
2). 菜品修改
当在后台修改菜品数据时为了保证Redis缓存中的数据和数据库中的数据时刻保持一致当修改后需要清空对应的缓存数据。用户再次访问时还是先从数据库中查询同时再把查询的结果存储到Redis中这样就能保证缓存和数据库的数据保持一致。
**进入后台**修改蜀味牛蛙分类下的任意一个菜品当前分类的菜品数据已在Redis中缓存
修改 **查看Redis中的缓存数据**说明修改时已清空缓存 用户再次访问同一个菜品分类时需要先查询数据库再把结果同步到Redis中保证了两者数据一致性。
其它功能测试步骤基本一致自已测试即可。
1.5 代码提交
2. 缓存套餐
2.1 Spring Cache
2.1.1 介绍
Spring Cache 是一个框架实现了基于注解的缓存功能只需要简单地加一个注解就能实现缓存功能。
Spring Cache 提供了一层抽象底层可以切换不同的缓存实现例如
EHCacheCaffeineRedis(常用)
起步依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId version2.7.3/version
/dependency2.1.2 常用注解
在SpringCache中提供了很多缓存操作的注解常见的是以下的几个
注解说明EnableCaching开启缓存注解功能通常加在启动类上Cacheable在方法执行前先查询缓存中是否有数据如果有数据则直接返回缓存数据如果没有缓存数据调用方法并将方法返回值放到缓存中CachePut将方法的返回值放到缓存中CacheEvict将一条或多条数据从缓存中删除
在spring boot项目中使用缓存技术只需在项目中导入相关缓存技术的依赖包并在启动类上使用EnableCaching开启缓存支持即可。
例如使用Redis作为缓存技术只需要导入Spring data Redis的maven坐标即可。
2.1.3 入门案例
1). 环境准备
**导入基础工程:**底层已使用Redis缓存实现
基础环境的代码在我们今天的资料中已经准备好了 大家只需要将这个工程导入进来就可以了。导入进来的工程结构如下 数据库准备:
创建名为spring_cache_demo数据库将springcachedemo.sql脚本直接导入数据库中。 引导类上加EnableCaching:
package com.itheima;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;Slf4j
SpringBootApplication
EnableCaching//开启缓存注解功能
public class CacheDemoApplication {public static void main(String[] args) {SpringApplication.run(CacheDemoApplication.class,args);log.info(项目启动成功...);}
}2). CachePut注解
CachePut 说明
作用: 将方法返回值放入缓存
value: 缓存的名称, 每个缓存名称下面可以有很多key
key: 缓存的key ---------- 支持Spring的表达式语言SPEL语法
在save方法上加注解CachePut
当前UserController的save方法是用来保存用户信息的我们希望在该用户信息保存到数据库的同时也往缓存中缓存一份数据我们可以在save方法上加上注解 CachePut用法如下 /*** CachePut将方法返回值放入缓存* value缓存的名称每个缓存名称下面可以有多个key* key缓存的key*/PostMappingCachePut(value userCache, key #user.id)//key的生成userCache::1public User save(RequestBody User user){userMapper.insert(user);return user;}**说明**key的写法如下
#user.id : #user指的是方法形参的名称, id指的是user的id属性 , 也就是使用user的id属性作为key ;
#result.id : #result代表方法返回值该表达式 代表以返回对象的id属性作为key
#p0.id#p0指的是方法中的第一个参数id指的是第一个参数的id属性,也就是使用第一个参数的id属性作为key ;
#a0.id#a0指的是方法中的第一个参数id指的是第一个参数的id属性,也就是使用第一个参数的id属性作为key ;
#root.args[0].id:#root.args[0]指的是方法中的第一个参数id指的是第一个参数的id属性,也就是使用第一个参数
的id属性作为key ;
启动服务,通过swagger接口文档测试访问UserController的save()方法
因为id是自增所以不需要设置id属性 查看user表中的数据 查看Redis中的数据 3). Cacheable注解
Cacheable 说明:
作用: 在方法执行前spring先查看缓存中是否有数据如果有数据则直接返回缓存数据若没有数据调用方法并将方法返回值放到缓存中
value: 缓存的名称每个缓存名称下面可以有多个key
key: 缓存的key ---------- 支持Spring的表达式语言SPEL语法
在getById上加注解Cacheable /*** Cacheable在方法执行前spring先查看缓存中是否有数据如果有数据则直接返回缓存数据若没有数据 *调用方法并将方法返回值放到缓存中* value缓存的名称每个缓存名称下面可以有多个key* key缓存的key*/GetMappingCacheable(cacheNames userCache,key#id)public User getById(Long id){User user userMapper.getById(id);return user;}重启服务,通过swagger接口文档测试访问UserController的getById()方法
第一次访问会请求我们controller的方法查询数据库。后面再查询相同的id就直接从Redis中查询数据不用再查询数据库了就说明缓存生效了。
提前在redis中手动删除掉id1的用户数据 **查看控制台sql语句**说明从数据库查询的用户数据 **查看Redis中的缓存数据**说明已成功缓存 再次查询相同id的数据时直接从redis中直接获取不再查询数据库。
4). CacheEvict注解
CacheEvict 说明
作用: 清理指定缓存
value: 缓存的名称每个缓存名称下面可以有多个key
key: 缓存的key ---------- 支持Spring的表达式语言SPEL语法
在 delete 方法上加注解CacheEvict DeleteMappingCacheEvict(cacheNames userCache,key #id)//删除某个key对应的缓存数据public void deleteById(Long id){userMapper.deleteById(id);}DeleteMapping(/delAll)CacheEvict(cacheNames userCache,allEntries true)//删除userCache下所有的缓存数据public void deleteAll(){userMapper.deleteAll();}重启服务,通过swagger接口文档测试访问UserController的deleteAll()方法 **查看user表**数据清空 查询Redis缓存数据
2.2 实现思路
实现步骤
1). 导入Spring Cache和Redis相关maven坐标
2). 在启动类上加入EnableCaching注解开启缓存注解功能
3). 在用户端接口SetmealController的 list 方法上加入Cacheable注解
4). 在管理端接口SetmealController的 save、delete、update、startOrStop等方法上加入CacheEvict注解
2.3 代码开发
按照上述实现步骤
1). 导入Spring Cache和Redis相关maven坐标(已实现)
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-data-redis/artifactId
/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-cache/artifactId
/dependency2). 在启动类上加入EnableCaching注解开启缓存注解功能
package com.sky;import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.transaction.annotation.EnableTransactionManagement;SpringBootApplication
EnableTransactionManagement //开启注解方式的事务管理
Slf4j
EnableCaching
public class SkyApplication {public static void main(String[] args) {SpringApplication.run(SkyApplication.class, args);log.info(server started);}
}3). 在用户端接口SetmealController的 list 方法上加入Cacheable注解 /*** 条件查询** param categoryId* return*/GetMapping(/list)ApiOperation(根据分类id查询套餐)Cacheable(cacheNames setmealCache,key #categoryId) //key: setmealCache::100public ResultListSetmeal list(Long categoryId) {Setmeal setmeal new Setmeal();setmeal.setCategoryId(categoryId);setmeal.setStatus(StatusConstant.ENABLE);ListSetmeal list setmealService.list(setmeal);return Result.success(list);}4). 在管理端接口SetmealController的 save、delete、update、startOrStop等方法上加入CacheEvict注解 /*** 新增套餐** param setmealDTO* return*/PostMappingApiOperation(新增套餐)CacheEvict(cacheNames setmealCache,key #setmealDTO.categoryId)//key: setmealCache::100public Result save(RequestBody SetmealDTO setmealDTO) {setmealService.saveWithDish(setmealDTO);return Result.success();}/*** 批量删除套餐** param ids* return*/DeleteMappingApiOperation(批量删除套餐)CacheEvict(cacheNames setmealCache,allEntries true)public Result delete(RequestParam ListLong ids) {setmealService.deleteBatch(ids);return Result.success();}/*** 修改套餐** param setmealDTO* return*/PutMappingApiOperation(修改套餐)CacheEvict(cacheNames setmealCache,allEntries true)public Result update(RequestBody SetmealDTO setmealDTO) {setmealService.update(setmealDTO);return Result.success();}/*** 套餐起售停售** param status* param id* return*/PostMapping(/status/{status})ApiOperation(套餐起售停售)CacheEvict(cacheNames setmealCache,allEntries true)public Result startOrStop(PathVariable Integer status, Long id) {setmealService.startOrStop(status, id);return Result.success();}2.4 功能测试
通过前后端联调方式来进行测试同时观察redis中缓存的套餐数据。和缓存菜品功能测试基本一致不再赘述。
2.5 代码提交
3. 添加购物车
3.1 需求分析和设计
3.1.1 产品原型
用户可以将菜品或者套餐添加到购物车。对于菜品来说如果设置了口味信息则需要选择规格后才能加入购物车;对于套餐来说可以直接点击 将当前套餐加入购物车。在购物车中可以修改菜品和套餐的数量也可以清空购物车。
效果图
3.1.2 接口设计
通过上述原型图设计出对应的添加购物车接口。 **说明**添加购物车时有可能添加菜品也有可能添加套餐。故传入参数要么是菜品id要么是套餐id。
3.1.3 表设计
用户的购物车数据也是需要保存在数据库中的购物车对应的数据表为shopping_cart表具体表结构如下
字段名数据类型说明备注idbigint主键自增namevarchar(32)商品名称冗余字段imagevarchar(255)商品图片路径冗余字段user_idbigint用户id逻辑外键dish_idbigint菜品id逻辑外键setmeal_idbigint套餐id逻辑外键dish_flavorvarchar(50)菜品口味numberint商品数量amountdecimal(10,2)商品单价冗余字段create_timedatetime创建时间
说明
购物车数据是关联用户的在表结构中我们需要记录每一个用户的购物车数据是哪些菜品列表展示出来的既有套餐又有菜品如果用户选择的是套餐就保存套餐ID(setmeal_id)如果用户选择的是菜品就保存菜品ID(dish_id)对同一个菜品/套餐如果选择多份不需要添加多条记录增加数量number即可
3.2 代码开发
3.2.1 DTO设计
根据添加购物车接口的参数设计DTO 在sky-pojo模块ShoppingCartDTO.java已定义
package com.sky.dto;import lombok.Data;
import java.io.Serializable;Data
public class ShoppingCartDTO implements Serializable {private Long dishId;private Long setmealId;private String dishFlavor;}3.2.2 Controller层
根据添加购物车接口创建ShoppingCartController
package com.sky.controller.user;import com.sky.dto.ShoppingCartDTO;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;/*** 购物车*/
RestController
RequestMapping(/user/shoppingCart)
Slf4j
Api(tags C端-购物车接口)
public class ShoppingCartController {Autowiredprivate ShoppingCartService shoppingCartService;/*** 添加购物车* param shoppingCartDTO* return*/PostMapping(/add)ApiOperation(添加购物车)public ResultString add(RequestBody ShoppingCartDTO shoppingCartDTO){log.info(添加购物车{}, shoppingCartDTO);shoppingCartService.addShoppingCart(shoppingCartDTO);//后绪步骤实现return Result.success();}
}3.2.3 Service层接口
创建ShoppingCartService接口
package com.sky.service;import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.ShoppingCart;
import java.util.List;public interface ShoppingCartService {/*** 添加购物车* param shoppingCartDTO*/void addShoppingCart(ShoppingCartDTO shoppingCartDTO);
}3.2.4 Service层实现类
创建ShoppingCartServiceImpl实现类并实现add方法
package com.sky.service.impl;import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.service.ShoppingCartService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;Service
public class ShoppingCartServiceImpl implements ShoppingCartService {Autowiredprivate ShoppingCartMapper shoppingCartMapper;Autowiredprivate DishMapper dishMapper;Autowiredprivate SetmealMapper setmealMapper;/*** 添加购物车** param shoppingCartDTO*/public void addShoppingCart(ShoppingCartDTO shoppingCartDTO) {ShoppingCart shoppingCart new ShoppingCart();BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);//只能查询自己的购物车数据shoppingCart.setUserId(BaseContext.getCurrentId());//判断当前商品是否在购物车中ListShoppingCart shoppingCartList shoppingCartMapper.list(shoppingCart);if (shoppingCartList ! null shoppingCartList.size() 1) {//如果已经存在就更新数量数量加1shoppingCart shoppingCartList.get(0);shoppingCart.setNumber(shoppingCart.getNumber() 1);shoppingCartMapper.updateNumberById(shoppingCart);} else {//如果不存在插入数据数量就是1//判断当前添加到购物车的是菜品还是套餐Long dishId shoppingCartDTO.getDishId();if (dishId ! null) {//添加到购物车的是菜品Dish dish dishMapper.getById(dishId);shoppingCart.setName(dish.getName());shoppingCart.setImage(dish.getImage());shoppingCart.setAmount(dish.getPrice());} else {//添加到购物车的是套餐Setmeal setmeal setmealMapper.getById(shoppingCartDTO.getSetmealId());shoppingCart.setName(setmeal.getName());shoppingCart.setImage(setmeal.getImage());shoppingCart.setAmount(setmeal.getPrice());}shoppingCart.setNumber(1);shoppingCart.setCreateTime(LocalDateTime.now());shoppingCartMapper.insert(shoppingCart);}}
}3.2.5 Mapper层
创建ShoppingCartMapper接口:
package com.sky.mapper;import com.sky.entity.ShoppingCart;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Update;
import java.util.List;Mapper
public interface ShoppingCartMapper {/*** 条件查询** param shoppingCart* return*/ListShoppingCart list(ShoppingCart shoppingCart);/*** 更新商品数量** param shoppingCart*/Update(update shopping_cart set number #{number} where id #{id})void updateNumberById(ShoppingCart shoppingCart);/*** 插入购物车数据** param shoppingCart*/Insert(insert into shopping_cart (name, user_id, dish_id, setmeal_id, dish_flavor, number, amount, image, create_time) values (#{name},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{image},#{createTime}))void insert(ShoppingCart shoppingCart);}创建ShoppingCartMapper.xml
?xml version1.0 encodingUTF-8 ?
!DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd
mapper namespacecom.sky.mapper.ShoppingCartMapperselect idlist parameterTypeShoppingCart resultTypeShoppingCartselect * from shopping_cartwhereif testuserId ! nulland user_id #{userId}/ifif testdishId ! nulland dish_id #{dishId}/ifif testsetmealId ! nulland setmeal_id #{setmealId}/ifif testdishFlavor ! nulland dish_flavor #{dishFlavor}/if/whereorder by create_time desc/select
/mapper3.3 功能测试
进入小程序添加菜品 加入购物车查询数据库 因为现在没有实现查看购物车功能所以只能在表中进行查看。
在前后联调时后台可通断点方式启动查看运行的每一步。
3.4 代码提交
4. 查看购物车
4.1 需求分析和设计
4.1.1 产品原型
当用户添加完菜品和套餐后可进入到购物车中查看购物中的菜品和套餐。 4.1.2 接口设计 4.2 代码开发
4.2.1 Controller层
在ShoppingCartController中创建查看购物车的方法 /*** 查看购物车* return*/GetMapping(/list)ApiOperation(查看购物车)public ResultListShoppingCart list(){return Result.success(shoppingCartService.showShoppingCart());}4.2.2 Service层接口
在ShoppingCartService接口中声明查看购物车的方法 /*** 查看购物车* return*/ListShoppingCart showShoppingCart();4.2.3 Service层实现类
在ShoppingCartServiceImpl中实现查看购物车的方法 /*** 查看购物车* return*/public ListShoppingCart showShoppingCart() {return shoppingCartMapper.list(ShoppingCart.builder().userId(BaseContext.getCurrentId()).build());}4.3 功能测试
当进入小程序时就会发起查看购物车的请求 点击购物车图标 测试成功。
4.4 代码提交
5. 清空购物车
5.1 需求分析和设计
5.1.1 产品原型
当点击清空按钮时会把购物车中的数据全部清空。 5.1.2 接口设计 5.2 代码开发
5.2.1 Controller层
在ShoppingCartController中创建清空购物车的方法 /*** 清空购物车商品* return*/DeleteMapping(/clean)ApiOperation(清空购物车商品)public ResultString clean(){shoppingCartService.cleanShoppingCart();return Result.success();}5.2.2 Service层接口
在ShoppingCartService接口中声明清空购物车的方法 /*** 清空购物车商品*/void cleanShoppingCart();5.2.3 Service层实现类
在ShoppingCartServiceImpl中实现清空购物车的方法 /*** 清空购物车商品*/public void cleanShoppingCart() {shoppingCartMapper.deleteByUserId(BaseContext.getCurrentId());}5.2.4 Mapper层
在ShoppingCartMapper接口中创建删除购物车数据的方法 /*** 根据用户id删除购物车数据** param userId*/Delete(delete from shopping_cart where user_id #{userId})void deleteByUserId(Long userId);5.3 功能测试
进入到购物车页面 点击清空 查看数据库中的数据 说明当前用户的购物车数据已全部删除。
5.4 代码提交