缓存菜品
后端服务都去查询数据库,对数据库访问压力增大。
解决方式:使用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);
}