苍穹外卖day04笔记

❔根据分类查菜品 两种写法区别

//1.根据分类查所有的菜品
public List<Dish> list(Long categoryId) {
        List<Dish> list = dishMapper.selectByCategoryId(categoryId);
        return list;
    }
//2.根据分类查到的菜品必须是启用状态的菜品
public List<Dish> list(Long categoryId) {
    Dish dish = Dish.builder()
        .categoryId(categoryId)
        .status(StatusConstant.ENABLE)
        .build();
    return dishMapper.list(dish);
}

⛏同样根据id查 :一个加了@pathvariable一个没有,区别:传入的参数是否是映射路径的一部分,是/dish/{id},否:/dish?id=3

❔修改数据库的值时,两种传参办法

⛏传入实体:适合多字段修改

void update(Dish dish);

⛏:传入id:仅修改某特定字段

void updateStatus(@Param("id") Long id, @Param("status") Integer status);

❔关于启用禁用的实现逻辑

可以不直接给数据库传入状态和id信息 而直接构造(builder)实体,可以复用之前的update方法 不用重写方法。

//我的写法
public void startOrStop(Integer status, Long id) {
        //根据套餐id查询对应菜品并查询菜品状态,如果关联菜品都在停售发出警告
        //1.setmeal_dish表 找到菜品id<集合>
        List<SetmealDish> dishIds = setmealDishMapper.getBySetmealId(id);
        dishIds.forEach(dishId -> {
            //2.dish表 根据菜品id判断菜品状态
            Dish dish = dishMapper.getById(dishId.getId());
            if(dish.getStatus() == StatusConstant.DISABLE){
                throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
            }
            //否则插入数据
            Setmeal setmeal = Setmeal.builder()
                    .status(status)
                    .id(id)
                    .build();
            setmealMapper.update(setmeal);

        });
    //问题:N+1 / 性能问题:查出所有关联 → 对每个关联再查一次菜品 → 可能再更新。可以用一条 SQL统计“停售菜品数量”
  //修改:若是“启售”,才需要校验关联菜品是否全部启售 先判断 少做查询
    //启售时只有校验通过才会执行到这里(因为没抛异常)。停售时直接更新(不需要校验)。
   public void startOrStop(Integer status, Long id) {
        //如果关联菜品有一个停售发出警告
        //先判断是否启售 如果启售再做后续查询关系
        if (status == StatusConstant.ENABLE) {
            // //1.setmeal_dish表 找到菜品id<集合> 再根据菜品id查找dish表(取status)
            //select d.* from dish d left join setmeal_dish sd on d.id = sd.dish_id[list]
            List<Dish> dishes = dishMapper.getBySealId(id);
            if (dishes != null && dishes.size() > 0) {
                dishes.forEach(dish -> {
                    if (dish.getStatus() == StatusConstant.DISABLE) {
                        throw new SetmealEnableFailedException(MessageConstant.SETMEAL_ENABLE_FAILED);
                    }
                });
            }

        }
        
        //插入数据
        Setmeal setmeal = Setmeal.builder()
                .status(status)
                .id(id)
                .build();
        setmealMapper.update(setmeal);

    }
 

Redis常见命令

Redis字符串类型常用命令:

●SET key value
设置指定key的值
●GETkey
获取指定key的值
●SETEX key seconds value(短信验证码)
设置指定key的值,并将key的过期时间设为seconds秒
●SETNX key value(分布式锁)
只有在key不存在时设置key的值

Redis哈希操作命令

Redis hash是一个string类型的 field和value的映射表,hash特别适合用于存储对象,常用命令:
●HSET key field value
将哈希表key中的字段field 的值设为value

●HGET key field
获取存储在哈希表中指定字段的值

●HDEL key field
删除存储在哈希表中的指定字段

●HKEYS key
获取哈希表中所有字段

●HVALS key
获取哈希表中所有值

Redis列表操作命令

Redis列表是简单的字符串列表,按照插入顺序排序,常用命令:
●LPUSH key value1 [value2]将一个或多个值插入到列表头部(左侧left)

●LRANGE key start stop
获取列表指定范围内的元素

●RPOP key
移除并获取列表最后一个元素(右侧rightR)

●LLEN key
获取列表长度

Redis 集合

Redis set是string类型的无序集合。集合成员是唯一的,集合中不能出现重复的数据,常用命令:

●SADD key member1 [member2]:向集合添加一 个或多个成员

●SMEMBERS key:返回集合中的所有成员

●SCARD key 获取集合的成员数

●SINTER key1 [key2] 返回给定所有集合的交集

●SUNION key1 [key2] 返回所有给定集合的并集

●SREM key member1 [member2]删除集合中一 个或多个成员

有序集合命令

Redis有序集合是string类型元素的集合,且不允许有重复成员。每个元素都会关联一个double类型的分数。 常用命令: .
●ZADD key score1 member1 [score2 member2]
向有序集合添加一个或多个成员
● ZRANGE key start stop [WITHSCORES](默认升序)
通过索弓|区间返回有序集合中指定区间内的成员
●ZINCRBY key increment member
有序集合中对指定成员的分数加上增量increment
● ZREM key member [member …
移除有序集合中的一个或多个成员

通用命令

Redis的通用命令是不分数据类型的,都可以使用的命令:
●KEYS pattern
查找所有符合给定模式( pattern)的key
●EXISTS key
检查给定key是否存在
●TYPE key
返回key所储存的值的类型
●DEL key
该命令用于在key存在是删除key

配置Spring date redis

操作步骤:
①导入Spring Data Redis的maven坐标[server/pom.xml]
②配置Redis数据源[application.ymal]
③编写配置类,创建RedisTemplate对象[config]
④通过Redis’ Template对象操作Redis

启动redis

控制台

#  服务启动
redis-server.exe redis.windows.conf
# 停止
ctrl c
# 连接redis服务
redis-cli.exe -h localhost -p 6379 -a 123456
#或者可以直接用图形化界面

### 苍穹外卖项目 Day3 学习笔记 #### 删除菜品的业务逻辑 在苍穹外卖项目的 Day3 学习笔记中,重点涉及了删除菜品的业务逻辑。首先需要判断菜品是否是起售状态,起售状态的菜品不能够被删除。此外,如果菜品包含在一个套餐中也是不能被删除的。只有在满足删除条件的情况下,才能执行删除操作[^1]。 #### 删除菜品的同时删除对应口味 在删除菜品的过程中,还需要删除与该菜品相关的所有口味信息。这是因为每个菜品可能有多个不同的口味选项,这些口味信息存储在另一个表中。因此,在删除菜品的同时,必须同步删除其对应的所有口味记录,以保持数据的一致性和完整性[^1]。 #### 示例代码:删除菜品及其口味 以下是一个示例代码,展示了如何实现删除菜品及其相关口味的功能: ```java public void deleteDish(Long dishId) { // 查询菜品的状态 Dish dish = dishMapper.getById(dishId); if (dish == null) { throw new NoSuchElementException("菜品不存在"); } // 判断菜品是否处于起售状态 if (dish.getStatus() == Status.ENABLED) { throw new IllegalStateException("起售状态的菜品不能删除"); } // 检查菜品是否包含在套餐中 boolean isInSetmeal = setmealMapper.checkIfInSetmeal(dishId); if (isInSetmeal) { throw new IllegalStateException("菜品包含在套餐中,不能删除"); } // 删除菜品 dishMapper.deleteById(dishId); // 删除菜品对应的口味 flavorMapper.deleteByDishId(dishId); } ``` 在这个示例代码中,首先通过 `dishMapper.getById` 获取菜品的信息,然后检查菜品是否存在以及是否处于起售状态。接着,使用 `setmealMapper.checkIfInSetmeal` 方法检查该菜品是否包含在任何套餐中。如果以上条件都不满足,则调用 `dishMapper.deleteById` 删除菜品,并通过 `flavorMapper.deleteByDishId` 删除与该菜品相关的所有口味信息。 #### 扩展功能 除了基本的删除功能外,还可以考虑添加一些扩展功能,例如日志记录、事务管理等,以确保数据操作的安全性和可靠性。此外,还可以为用户提供更详细的错误提示信息,帮助用户更好地理解为什么某些菜品无法被删除。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值