如何为Guava Cache的load()方法传入第二个Profile参数?
解决Guava Cache中多参数查询的缓存问题
看起来你踩了Guava Cache的一个常见坑:你的缓存键只用到了size参数,但实际上查询结果同时依赖size和Profile里的查询条件(比如employed)。之前的实现把这两个条件拆分开,导致缓存无法区分不同employed值的查询请求,自然会返回错误的结果。
接下来一步步给你解决这个问题:
1. 创建复合缓存键
Guava Cache的LoadingCache只支持单个键类型,所以我们需要把所有影响查询结果的参数封装成一个复合键类。这里推荐提取Profile中实际用于查询的字段(比如employed)和size组成键,更轻量高效:
import java.util.Objects; public class ProfileCacheKey { private final Integer size; private final Boolean employed; // 构造函数,给参数加默认值避免null导致键不一致 public ProfileCacheKey(Integer size, Boolean employed) { this.size = size == null ? 10 : size; this.employed = employed; } // 必须重写equals和hashCode,Guava靠这两个方法判断键是否相同 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ProfileCacheKey that = (ProfileCacheKey) o; return Objects.equals(size, that.size) && Objects.equals(employed, that.employed); } @Override public int hashCode() { return Objects.hash(size, employed); } }
2. 修改LoadingCache的定义
把缓存的键类型改成我们刚创建的ProfileCacheKey,并调整CacheLoader的load方法来接收这个复合键:
private LoadingCache<ProfileCacheKey, List<Profile>> loadingCache = CacheBuilder.newBuilder() .refreshAfterWrite(10, TimeUnit.MINUTES) .maximumSize(100) .build(new CacheLoader<ProfileCacheKey, List<Profile>>() { @Override public List<Profile> load(ProfileCacheKey key) throws Exception { // 从复合键中取出参数,构建DAO需要的Profile对象 Profile profile = new Profile(); profile.setEmployed(key.employed); return profileDAO.getAllProfiles(profile, key.size); } });
3. 调整业务方法的调用逻辑
修改getAllProfiles方法,用复合键去获取缓存:
public List<Profile> getAllProfiles(Profile profile, Integer size) throws Exception { // 从传入的Profile中提取查询参数,创建复合键 ProfileCacheKey key = new ProfileCacheKey(size, profile.getEmployed()); return loadingCache.get(key); }
为什么之前的尝试会失败?
- 你试图给
CacheLoader.load()加第二个参数:Guava的LoadingCache设计就是单键映射,所以CacheLoader只支持单个参数的load方法,无法直接传多个参数。 - 用
Callable的尝试:你返回的是Profile类型,但缓存的值是List<Profile>,类型不匹配;而且你还是没解决键的问题,依然只靠size作为键,无法区分不同查询条件。
额外建议
- 如果
Profile里有多个查询参数(不止employed),记得把所有参数都加到ProfileCacheKey里,并重写equals和hashCode。 - 若你想直接用整个
Profile对象作为键的一部分,一定要确保Profile类正确重写了equals和hashCode,否则缓存会出现键不匹配的问题。
内容的提问来源于stack exchange,提问作者SVill
相关产品推荐
相关产品推荐

