Guava Cache:如何处理空值

SVi*_*ill 2 java null return-value guava

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

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);
    }
Run Code Online (Sandbox Code Playgroud)

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

com.google.common.cache.CacheLoader$InvalidCacheLoadException: CacheLoader returned null for key A01|Peter
Run Code Online (Sandbox Code Playgroud)

如果数据库中没有匹配项,我只想返回一个空的 List(Profile),但我的 if 语句失败了。对于这个特定用例,有没有办法解决这个错误?

C. *_*non 9

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

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我相信这种方法在效率方面优于任何涉及使用异常的方法。


Emi*_*347 8

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

  • 这是最好的答案。可选与番石榴缓存一起正确工作,并使其更清楚它可以具有什么值。 (2认同)

小智 2

在代码中进行更改以检查第一个配置文件是否为空(使用配置文件== 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);
    }
Run Code Online (Sandbox Code Playgroud)

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