Comment éviter la mise en cache lorsque les valeurs sont nulles?
j'utilise la goyave pour cacher des données chaudes.Quand les données n'existent pas dans le cache,je dois les récupérer dans une base de données comme celle-ci.
public final static LoadingCache<ObjectId, User> UID2UCache = CacheBuilder.newBuilder()
//.maximumSize(2000)
.weakKeys()
.weakValues()
.expireAfterAccess(10, TimeUnit.MINUTES)
.build(
new CacheLoader<ObjectId, User>() {
@Override
public User load(ObjectId k) throws Exception {
User u = DataLoader.datastore.find(User.class).field("_id").equal(k).get();
return u;
}
});
mon problème est que lorsque les données n'existent pas dans la base de données non plus, je préfère retourner null et ne pas faire de mise en cache. Mais guava juste enregistrer null avec la clé dans le cache et jeter l'exception quand je l'obtiens
com.Google.commun.cache.CacheLoader $ InvalidCacheLoadException: CacheLoader retourné null pour la clé shisoft.
alors, comment éviter la mise en cache des valeurs nulles?
4 réponses
il suffit de lancer une Exception si l'utilisateur n'est pas trouvé et l'attraper dans le code client en utilisant get(key)
méthode.
new CacheLoader<ObjectId, User>() {
@Override
public User load(ObjectId k) throws Exception {
User u = DataLoader.datastore.find(User.class).field("_id").equal(k).get();
if (u != null) {
return u;
} else {
throw new UserNotFoundException();
}
}
}
CacheLoader.load(K)
Javadoc:
Returns: the value associated with key; must not be null Throws: Exception - if unable to load the result
répondre à vos doutes sur la mise en cache des valeurs nulles:
renvoie la valeur associée à la clé dans ce cache, premier chargement cette valeur, si nécessaire. pas d'état observable associé à ce le cache est modifié jusqu'à chargement terminé.
(LoadingCache.get(K)
Javadoc)
si vous lancez une exception, la charge n'est pas considérée comme complète, donc aucune nouvelle valeur n'est mise en cache.
EDIT:
Notez que dans la Caféine, qui est une sorte de cache Goyave 2.0 et "fournit une cache en mémoire à l'aide D'une API Google Goyave inspiré" vous retour null
load
méthode:
Returns: the value associated with key or null if not found
si vous envisagez de migrer, votre chargeur de données pourrait librement revenir lorsque l'utilisateur n'est pas trouvé.
solution Simple: utiliser com.google.common.base.Optional<User>
au lieu de User
en tant que valeur.
public final static LoadingCache<ObjectId, Optional<User>> UID2UCache = CacheBuilder.newBuilder()
...
.build(
new CacheLoader<ObjectId, Optional<User>>() {
@Override
public Optional<User> load(ObjectId k) throws Exception {
return Optional.fromNullable(DataLoader.datastore.find(User.class).field("_id").equal(k).get());
}
});
EDIT: je pense que la réponse de @Xaerxess est meilleure.
fait face au même problème, parce que les valeurs manquantes dans la source faisait partie du flux de travail normal. Je n'ai rien trouvé de mieux que d'écrire du code moi-même en utilisant getIfPresent
,get
et put
méthodes. Voir la méthode ci-dessous, où local
Cache<Object, Object>
:
private <K, V> V getFromLocalCache(K key, Supplier<V> fallback) {
@SuppressWarnings("unchecked")
V s = (V) local.getIfPresent(key);
if (s != null) {
return s;
} else {
V value = fallback.get();
if (value != null) {
local.put(key, value);
}
return value;
}
}
lorsque vous voulez mettre en cache des valeurs NULL, vous pouvez utiliser d'autres portées qui se comportent comme NULL.
et avant de donner la solution, je vous suggérerais de ne pas exposer LoadingCache à l'extérieur. Vous devriez plutôt utiliser la méthode pour restreindre la portée du Cache.
Par exemple, vous pouvez utiliser LoadingCache<ObjectId, List<User>>
comme type de retour. Et puis, vous pourriez retourner la liste vide quand vous pourriez ' N récupérer des valeurs de la base de données. Vous pouvez utiliser -1 Comme entier ou Long NULL valeur, vous pourrait utiliser "" comme chaîne de caractères NULL valeur, et ainsi de suite. Après cela, vous devriez fournir une méthode pour handler la valeur nulle.
when(value equals NULL(-1|"")){
return null;
}