You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为按不同条件返回同类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 17:15:04