如何为按不同条件返回同类DTO列表的方法配置@Cacheable缓存?
直接给三个方法标注相同@Cacheable("Dishes_DTO")会有冲突问题
Spring Cache默认使用SimpleKeyGenerator生成缓存键:
- 无参方法的默认缓存键都是
SimpleKey.EMPTY,你的getAllToday()和getAll()都是无参方法,共用同一个缓存名的话,后执行的方法会直接覆盖前者的缓存数据,导致返回结果错误。 - 带参数的
getDishHistoryByRestaurant(int restaurantId)默认用入参值作为缓存键,只要入参和前两个方法的默认键不重合就不会冲突,但前两个无参方法的覆盖问题无法避免。
正确的缓存注解配置方案
推荐手动指定缓存键,既可以共用同一个缓存名统一管理,也能完全避免键冲突,改造后的代码如下:
// 查当日菜品,缓存键加上日期,避免跨日返回旧数据 @Cacheable(value = "Dishes_DTO", key = "'getAllToday_' + T(java.time.LocalDate).now(clock)") public List<DishResponseDTO> getAllToday() { List<Dish> dishlsit = dishRepository.getAllByDateAdded(LocalDate.now(clock)); return dishlsit.stream() .map(DishMapper::toDishResponseDTO) .collect(Collectors.toList()); } // 查全量菜品,用方法名作为缓存键 @Cacheable(value = "Dishes_DTO", key = "'getAll'") public List<DishResponseDTO> getAll() { List<Dish> dishlsit = dishRepository.findAll(); return dishlsit.stream() .map(DishMapper::toDishResponseDTO) .collect(Collectors.toList()); } // 按餐厅查历史,缓存键拼接方法名和餐厅ID @Cacheable(value = "Dishes_DTO", key = "'getDishHistoryByRestaurant_' + #restaurantId") public List<DishResponseDTO> getDishHistoryByRestaurant(int restaurantId) { return dishRepository.getAllByRestaurantId(restaurantId) .stream() .map(DishMapper::toDishResponseDTO) .collect(Collectors.toList()); }
额外注意事项
- 给
getAllToday的缓存单独设置过期时间,最好设置为当日结束自动失效,避免缓存残留旧日期的菜品数据。 - 如果存在菜品新增、修改、删除的操作,要配合
@CacheEvict注解清理Dishes_DTO缓存,避免出现脏数据。 - 也可以选择给三个方法分配不同的缓存名(比如
Dishes_Today、Dishes_All、Dishes_ByRestaurant),无需手动指定键也不会冲突,但后续缓存清理、过期配置需要分别处理,灵活性低于共用缓存名的方案。
内容的提问来源于stack exchange,提问作者user16722881
相关产品推荐
相关产品推荐

