黑马苍穹外卖6 清理redis缓存+Spring Cache+购物车的增删改查

news2025/1/18 6:26:54

缓存菜品

后端服务都去查询数据库,对数据库访问压力增大。
解决方式:使用redis来缓存菜品,用内存比磁盘性能更高。
在这里插入图片描述
在这里插入图片描述
key :dish_分类id
String key= “dish_” + categoryId;

@RestController("userDishController")
@RequestMapping("/user/dish")
@Slf4j
@Api(tags = "C端-菜品浏览接口")
public class DishController {

    @Autowired
    private DishService dishService;

    @Autowired
    private RedisTemplate redisTemplate;//注入redis对象

    /**
     * 根据分类id查询菜品
     *
     * @param categoryId
     * @return
     */
    @GetMapping("/list")
    @ApiOperation("根据分类id查询菜品")
    public Result<List<DishVO>> list(Long categoryId) {
        //构造redis中的key来查询分类下的菜单
        String key = "dish_" + categoryId;
        //查询redis中是否存在菜品,有则读取
        List<DishVO> list = (List<DishVO>) 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);//查询起售中的菜品

        list = dishService.listWithFlavor(dish);
        redisTemplate.opsForValue().set(key,list);
        return Result.success(list);
    }

}

当数据变更[增删改]时要清除缓存

private void cleanCache(String pattern) {
        Set keys = redisTemplate.keys(pattern);
        redisTemplate.delete(keys);
    }
@ApiOperation("批量删除菜品")
    @DeleteMapping
    public Result delete(@RequestParam List<Long> ids) {//@RequestParam让Spring去解析字符串,然后将分割的字符封装到集合对象中
        dishService.deleteBatch(ids);//批量删除

        //更新缓存,清理所有,将所有的菜品缓存数据清理,所有以dish_开头的key
        cleanCache("dish_*");

        return Result.success();
    }
@PostMapping
    @ApiOperation("菜品新增")
    public Result save(@RequestBody DishDTO dishDTO) {

        dishService.saveWithFlavor(dishDTO);
        //清理缓存
        cleanCache("dish_" + dishDTO.getCategoryId());//精确清理

        return Result.success();
    }

缓存套餐

Spring Cache

框架,实现了基于注解的缓存功能。
底层可以切换不同的缓存实现:
EHCache
Caffeine
Redis
在这里插入图片描述
@CachePut这个注释将方法的返回结果,user对象保存到Redis中,同时生成动态的key,userCache::user.id

@CachePut(cacheNames="userCache",key="abs")//Spring Cache缓存数据,key的生成:userCache:abc
@CachePut(cacheNames="userCache",key="#user.id")//与形参保持一致,或者
@CachePut(cacheNames="userCache",key="#result.id")//返回值result,或者
@CachePut(cacheNames="userCache",key="#p0.id")//获得当前方法的第一个参数user,或者
@CachePut(cacheNames="userCache",key="#a0.id")//获得当前方法的第一个参数user,或者
@CachePut(cacheNames="userCache",key="#root.args[0].id")//获得当前方法的第一个参数user
public User save(@RequestBody User user){
	userMapper.insert(user);
	return result;
}

插入完数据后,数据库生成的主键值会自动赋给user对象
Redis可以形成树形结构

@Cacheable注解

@Cacheable(cahceNames="userCache"),key="#id")//key的生成,userCache::10
public User getById(Long id){
	User user = userMapper.getById(id);
	return user;
}

@CacheEvict一次清理一条数据

@CacheEvict(cahceNames="userCache"),key="#id")//key的生成,userCache::10
public void deleteById(Long id){
	userMapper.deleteById(id);
}

清除所有数据

@CacheEvict(cahceNames="userCache"),allEntries=true)//userCache下的所有键值对
public void deleteAlld(){
	userMapper.deleteAll();
}

回归项目:缓存套餐
1.展示套餐—先查cache中,再数据库查+导Redis

 @GetMapping("/list")
    @ApiOperation("根据分类id查询套餐")
    @Cacheable(cacheNames = "setMealCache",key = "#categoryId")//key : setMealCache::1
    public Result<List<Setmeal>> list(Long categoryId) {
        Setmeal setmeal = new Setmeal();
        setmeal.setCategoryId(categoryId);
        setmeal.setStatus(StatusConstant.ENABLE);

        List<Setmeal> list = setmealService.list(setmeal);
        return Result.success(list);
    }

2.增删

 @PostMapping
    @ApiOperation("新增套餐")
    @CacheEvict(cacheNames = "setMealCache",key = "#setmealDTO.categoryId")//精确清理key:setmealCache::100
    public Result save(@RequestBody SetmealDTO setmealDTO) {
        setmealService.saveWithDish(setmealDTO);
        return Result.success();
    }
@DeleteMapping
    @ApiOperation("批量删除套餐")
    @CacheEvict(cacheNames = "setMealCache",allEntries = true)
    public Result delete(@RequestParam List<Long> ids){
        setmealService.deleteBatch(ids);
        return Result.success();
    }

添加购物车-增改查

在这里插入图片描述

在这里插入图片描述
上图是表中每个字段的属性。
购物车表效果:
在这里插入图片描述

1.增–添加购物车

判断商品是否已经存在,存在就+1,不存在则插入数据
(1)先根据user_id和菜品ID/套餐ID查表
Controller:

@PostMapping("/add")
    @ApiOperation("添加购物车")
    public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO){
        shoppingCartService.add(shoppingCartDTO);
        return Result.success();
    }

Setvice:

public void add(ShoppingCartDTO shoppingCartDTO) {
        ShoppingCart shoppingCart = new ShoppingCart();
        BeanUtils.copyProperties(shoppingCartDTO, shoppingCart);//属性拷贝
        Long currentId = BaseContext.getCurrentId();
         shoppingCart.setUserId(currentId);
        //先查询购物车中是否存在
        List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);//查表
        if (list != null && list.size() > 0) {
            //存在则更新数据的数量
            ShoppingCart cart = list.get(0);
            cart.setNumber(cart.getNumber() + 1);
            shoppingCartMapper.updateNumberById(cart);//更新表
        }
        else {
            //不存在则添加数据
            Long dishId = shoppingCart.getDishId();
            Long setmealId = shoppingCart.getSetmealId();
            //判断添加的这条是菜还是套餐
            if (dishId != null) {
                Dish dish = dishMapper.getById(dishId);
                shoppingCart.setName(dish.getName());
                shoppingCart.setAmount(dish.getPrice());
                shoppingCart.setImage(dish.getImage());
            } else if (setmealId != null) {
                Setmeal setmeal = setmealMapper.getById(setmealId);
                shoppingCart.setImage(setmeal.getImage());
                shoppingCart.setAmount(setmeal.getPrice());
                shoppingCart.setName(setmeal.getName());
            }
            shoppingCart.setNumber(1);
            shoppingCart.setCreateTime(LocalDateTime.now());
            shoppingCartMapper.insert(shoppingCart);//插入表项
        }
    }

查:
mapper:

List<ShoppingCart> list(ShoppingCart shoppingCart);

动态xml

<select id="list" resultType="com.sky.entity.ShoppingCart">
        select * from shopping_cart
        <where>
            <if test="userId!=null">and user_id=#{userId}</if>
            <if test="dishId!=null">and dish_id=#{dishId}</if>
            <if test="setmealId!=null">and setmeal_id=#{setmealId}</if>
            <if test="dishFlavor!=null">and dish_flavor=#{dishFlavor}</if>
        </where>

    </select>

改:
mapper:

@Update("update shopping_cart set number=#{number} where id=#{id}")
    void updateNumberById(ShoppingCart shoppingCart);

插:
mapper:

@Insert("insert into shopping_cart(name, image, user_id, dish_id, setmeal_id, dish_flavor, number, amount, create_time)"
        + "values (#{name},#{image},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{createTime})")
    void insert(ShoppingCart shoppingCart);

查看购物车

在这里插入图片描述
Controller:

  @GetMapping("/list")
    @ApiOperation("查询购物车数据")
    public Result<List<ShoppingCart>> list(){
        return Result.success(shoppingCartService.list());
    }

Service:

@Override
    public List<ShoppingCart> list() {
        Long currentId = BaseContext.getCurrentId();
        ShoppingCart shoppingCart = ShoppingCart//构造对象
            .builder()
            .userId(currentId)
            .build();
        return shoppingCartMapper.list(shoppingCart);
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1853300.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何配置taro

文章目录 step1. 全局安装wepacksetp2. 使用npm安装tarostep3. 项目初始化 使用taro时需要在本地配置好nodejs环境&#xff0c;关于如何配置nodejs可参考我的这篇博文 如何配置nodejs环境 step1. 全局安装wepack 使用指令npm install webpack -g即可 安装完成后可看到有wepa…

使用Vue+Antv-X6实现一个输送线可视化编辑器(支持拖拽、自定义连线、自定义节点等)

最近公司有这样的业务&#xff0c;要实现一个类似流程图的编辑器&#xff0c;可以拖拉拽之类的&#xff0c;网上寻找了一番&#xff0c;最终决定使用Antv-X6这个图形引擎&#xff0c;非常强大&#xff0c;文档多看几遍也就能上手使用了。感觉还不错就写个使用心得期望能帮助到同…

2000年 - 2022年 Fama-French三因子模型数据+代码

Fama-French三因子模型是由著名经济学家尤金法玛&#xff08;Eugene Fama&#xff09;和肯尼斯法兰奇&#xff08;Kenneth French&#xff09;提出的&#xff0c;旨在改进资本资产定价模型&#xff08;CAPM&#xff09;&#xff0c;更全面地解释资产收益率的变化。该模型认为&a…

论文笔记:Spatial-Temporal Interval Aware Sequential POI Recommendation

ICDE 2022 1 intro 1.1 背景 空间&#xff08;Spatial&#xff09;和时间&#xff08;Temporal&#xff09;信息是序列 POI 推荐中两个重要且相辅相成的因素。 空间因素&#xff08;如地理距离间隔&#xff09;可以在用户的历史轨迹呈现空间分簇现象时&#xff0c;细粒度刻画…

主流中间件--Redis

NOSQL 什么是NOSQL NoSQL(NoSQL Not Only SQL )&#xff0c;意即“不仅仅是SQL”&#xff0c;它泛指非关系型的数据库。 关系型数据库&#xff1a;以关系(由行和列组成的二维表)模型建模的数据库。简单理解&#xff1a;有表的就是关系型数据库。 NOSQL分类 Redis 什么是Redi…

L02_并发编程知识图谱

这些知识点你都掌握了吗&#xff1f;大家可以对着问题看下自己掌握程度如何&#xff1f;对于没掌握的知识点&#xff0c;大家自行网上搜索&#xff0c;都会有对应答案&#xff0c;本文不做知识点详细说明&#xff0c;只做简要文字或图示引导。 并发理论 并发编程Bug源头 为了…

反射机制详解

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a;Java从入门到精通 ✨特色专栏&#xff…

读书笔记之智能商业

智能商业 本书试图勾勒的是未来商业的大蓝图&#xff0c;目前中国市场变化速度非常之快&#xff0c;作者用了一个词来形容现在市场发展的特殊性&#xff1a;三浪叠加 1.0浪&#xff1a;传统的零售2.0浪&#xff1a;国美、苏宁为代表的综合商城模式3.0浪&#xff1a;以淘宝为代…

STM32学习之一:什么是STM32

目录 1.什么是STM32 2.STM32命名规则 3.STM32外设资源 4. STM32的系统架构 5. 从0到1搭建一个STM32工程 学习stm32已经很久了&#xff0c;因为种种原因&#xff0c;也有很久一段时间没接触过stm32了。等我捡起来的时候&#xff0c;发现很多都已经忘记了&#xff0c;重新捡…

【mysql】常用操作:维护用户/开启远程/忘记密码/常用命令

一、维护用户 1.1 创建用户 -- 语法 > CREATE USER [username][host] IDENTIFIED BY [password];-- 例子&#xff1a; -- 添加用户user007&#xff0c;密码123456&#xff0c;并且只能在本地可以登录 > CREATE USER user007localhost IDENTIFIED BY 123456; -- 添加用户…

宇哥强调!7月份必须开始强化阶段(附规划)

七月开始强化不晚&#xff0c;但是要开始了&#xff01; 张宇老师说&#xff1a;七月&#xff0c;也就是暑假是大家学习的最佳时机&#xff0c;这个时候要大量的做题&#xff01; 如果你是三月份开始备考的&#xff0c;那么到了七月份&#xff0c;基础应该复习的差不多了&…

wget:unable to resolve host address ...(已解决)

写在前面&#xff1a; 最近在学习Linux命令&#xff0c;此问题是在使用wget安装rar时出现的问题&#xff0c;记录一下解决的过程。仅供参考&#xff0c;若有不当的地方&#xff0c;恳请指正。如果对你有帮助&#xff0c;欢迎点赞&#xff0c;关注&#xff0c;收藏&#xff0c;…

基于YOLOv5+pyqt5的跌倒检测系统(含pyqt页面、训练好的模型)

简介 跌倒是老年人和身体不便者常见的意外事故&#xff0c;及时检测和处理跌倒事件对于保障他们的安全至关重要。为了提高对跌倒事件的监控效率&#xff0c;我们开发了一种基于YOLOv5目标检测模型的跌倒检测系统。本报告将详细介绍该系统的实际应用与实现&#xff0c;包括系统…

OpenCv形态学(一)

目录 形态学转换 结构元素 腐蚀 膨胀 开运算 闭运算 形态学梯度 顶帽 黑帽 图像轮廓 查找轮廓 绘制轮廓 形态学转换 形态变换是一些基于图像形状的简单操作。通常在二值图像上执行。它需要两个输入&#xff0c;一个是我们的原始图像&#xff0c;第二个是决定操作性…

Nginx Proxy Manager反向代理Jackett

1 说明 最近折腾nas&#xff0c;发现npm反向代理Jackett后出现无法访问的问题&#xff0c;是因为外网访问jackett (例如https://domain.com:7373/jackett/UI/Dashboard)时&#xff0c;url会被重定向到https://domain.com/jackett/UI/Login?ReturnUrl%2Fjackett%2FUI%2FDashbo…

基于matlab的K-means聚类图像分割

1 原理 K-means聚类算法在图像分割中的应用是基于一种无监督的学习方法&#xff0c;它将图像中的像素点或特征区域划分为K个不同的簇或类别。以下是K-means聚类算法用于图像分割的原理&#xff0c;包括步骤和公式&#xff1a; 1.1 原理概述 选择簇的数量(K)&#xff1a; 首先…

《数字图像处理与机器视觉》案例一(库尔勒香梨果梗提取和测量)

一、引言 果梗是判断水果新鲜程度的重要标志&#xff0c;对水果的贮藏和保鲜也具有重要的参考价值。库尔勒香梨分级标准中对果梗有明确要求&#xff0c;要求果梗完整&#xff0c;但由于库尔勒香梨果梗颜色与果实接近&#xff0c;用传统的简单阈值分割方法难以提取。因此&#…

双指针算法专题(移动零 复写零 快乐数)

目录 前言 1. 移动零 &#xff08;1&#xff09;题目及示例 &#xff08;2&#xff09;一般思路 &#xff08;3&#xff09;双指针解法 2. 复写零 &#xff08;1&#xff09;题目及示例 &#xff08;2&#xff09;一般解法 &#xff08;3&#xff09;双指针解法 3. 快…

Kubernetes相关生态

1、Prometheus、Metrics Server与Kubernetes监控体系 简介&#xff1a; Prometheus 项目与 Kubernetes 项目一样&#xff0c;也来自于 Google 的 Borg 体系&#xff0c;它的原型系统&#xff0c;叫作 BorgMon&#xff0c;是一个几乎与 Borg 同时诞生的内部监控系统 Pro…

AG32 MCU Start Kit 开发板快速入门及 21天体验活动

AG32 IDE开发环境搭建-完整版 海振远科技 2024-6-18 AG32 MCU开发板的使用 使用准备 在使用开发板前&#xff0c;请确认已经安装好开发环境。 安装环境过程&#xff0c;请参考文档《AG32 开发环境搭建.pdf》 上电&#xff1a; 给开发板5V 供电&#xff0c;打开开关&#…