如何使用" IN"来缓存数据库查询?运营商?

时间:2016-12-29 17:02:26

标签: spring caching

我使用Spring Boot和Spring Cache。我有一个方法,给定一个id列表,返回一个与这些id匹配的Food列表:

public List<Food> get(List<Integer> ids) {
    return "select * from FOOD where FOOD_ID in ids"; // << pseudo-code
}

我想按id缓存结果。想象一下我:

List<Food> foods = get(asList(1, 5, 7));

然后:

List<Food> foods = get(asList(1, 5));

我希望从缓存中检索ID为1的Food和ID为5的Food。有可能吗?

我知道我可以做一个像这样的方法:

@Cacheable(key = "id")
public Food getById(id){
    ...
}

并迭代id列表并每次调用它,但在这种情况下我不会利用IN SQL运算符,对吧?感谢。

1 个答案:

答案 0 :(得分:1)

Cacheable的key属性采用SpEL表达式来计算缓存键。所以你应该能够做类似

的事情
@Cacheable(key = "#ids.stream().map(b -> Integer.toString(b)).collect(Collectors.joining(",")))

这将要求id始终处于相同的顺序

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-annotations-cacheable-key

更好的选择是创建一个类来包装你能够为你生​​成缓存键的id,或者某种实用类函数。

没有@Cacheable的另一种可能的解决方案是将缓存管理器注入类中:

@Autowired
private CacheManager cacheManager;

然后,您可以通过名称

从缓存管理器中检索食物缓存
Cache cache = cacheManager.getCache('cache name');

然后你可以调整你的方法以获取id列表并手动添加并从缓存中获取值

cache.get(id);
cache.put(id, food);

您很可能仍然无法使用SQL IN子句,但您至少在方法内处理迭代,而不是在调用此方法的任何地方,并尽可能利用缓存。

public List<Food> get(List<Integer> ids) {
    List<Food> result = new ArrayList<>();

    for(Integer id : ids) {
        // Attempt to fetch from cache
        Food food = cache.get(id);

        if (food == null) {
            // Fetch from DB
            cache.put(id, food);
        }

        result.add(food);
    }

    return result;
}

相关的Javadocs:

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/CacheManager.html

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/Cache.html