番石榴缓存:如何处理空值



我已经构建了一个缓存,当您输入参数时,它会以列表格式返回一个值。 如果该值不在缓存中,它将转到数据库并检索它,将其放入缓存中以供将来参考:

private ProfileDAO profileDAO;
private String[] temp;
private LoadingCache<String, List<Profile>> loadingCache = CacheBuilder.newBuilder()
.refreshAfterWrite(5, TimeUnit.MINUTES)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build(
new CacheLoader<String, List<Profile>>() {
@Override
public List<Profile> load(String key) throws Exception {
logger.info("Running method to retrieve from database");
temp = key.split("\|");
String instance = temp[0];
String name = temp[1];
List<Profile> profiles= profileDAO.getProfileByFields(id, name);
if (profiles.isEmpty()) {
List<Profile> nullValue = new ArrayList<Profile>();
logger.info("Unable to find a value.");
return nullValue;
}
logger.info("Found a value");
return profileDAO.getProfileByFields(id, name);
}
}
);
public List<Profile> getProfileByFields(String id, String name) throws Exception {
String key = id.toLowerCase() + "|" + name.toLowerCase()
return loadingCache.get(key);
}

这似乎工作正常,但它没有考虑空值。 如果我查找不存在的条目,则会出现以下异常:

com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key A01|Peter

如果数据库中没有匹配项,我想简单地返回一个空的列表(配置文件(,但我的 if 语句失败了。 对于这个特定用例,有什么方法可以解决此错误吗?

虽然这感觉有点笨拙,但我认为这是一个更完整的解决方案(Suresh 的答案仅适用于集合(。

定义一个表示null的单例对象,并将该值插入缓存而不是null(在检索时转换为null(:

class MyDAO
{
static final Object NULL = new Object();
LoadingCache<String,Object> cache = CacheBuilder.newBuilder()
.build( new CacheLoader<>()
{
public Object load( String key )
{
Object value = database.get( key );
if( value == null )
return NULL;
return value;
}
});
Object get( String key )
{
Object value = cache.get( key );
if( value == NULL ) // use '==' to compare object references
return null;
return value;
}
}

我认为,就效率而言,这种方法比任何涉及使用例外的做法更可取。

使用可选的类Optional<Object>作为缓存值是最简单、最干净的方法。

在代码中进行更改以检查第一个配置文件是否为空(使用配置文件 == null ...(:

private ProfileDAO profileDAO;
private String[] temp;
private LoadingCache<String, List<Profile>> loadingCache = CacheBuilder.newBuilder()
.refreshAfterWrite(5, TimeUnit.MINUTES)
.expireAfterWrite(5, TimeUnit.MINUTES)
.build(
new CacheLoader<String, List<Profile>>() {
@Override
public List<Profile> load(String key) throws Exception {
logger.info("Running method to retrieve from database");
temp = key.split("\|");
String instance = temp[0];
String name = temp[1];
List<Profile> profiles= profileDAO.getProfileByFields(id, name);
if (profiles == null || profiles.isEmpty()) {
List<Profile> nullValue = new ArrayList<Profile>();
logger.info("Unable to find a value.");
return nullValue;
}
logger.info("Found a value");
return profileDAO.getProfileByFields(id, name);
}
}
);
public List<Profile> getProfileByFields(String id, String name) throws Exception {
String key = id.toLowerCase() + "|" + name.toLowerCase()
return loadingCache.get(key);
}

请检查此代码是否适合您的空值。

最新更新