2014-07-24 12 views
6

Sto lavorando con la Primavera e EHCacheCome aggiornare/rimuovere un elemento già memorizzato nella cache all'interno di una collezione di oggetti

ho il seguente metodo

@Override 
@Cacheable(value="products", key="#root.target.PRODUCTS") 
public Set<Product> findAll() { 
    return new LinkedHashSet<>(this.productRepository.findAll()); 
} 

Ho altri metodi di lavoro con @Cacheable e @CachePut e @CacheEvict.

Ora, immaginate il database restituisce 100 prodotti e sono memorizzati nella cache attraverso key="#root.target.PRODUCTS", poi altro metodo sarebbe inserto - aggiornamento - cancellato un elemento nel database. Pertanto i prodotti memorizzati nella cache tramite lo key="#root.target.PRODUCTS" non sono più gli stessi come il database.

Voglio dire, controllare i due seguenti due metodi, sono in grado di aggiornare/eliminare un elemento, e che stesso elemento viene memorizzato nella cache nell'altra key="#root.target.PRODUCTS"

@Override 
@CachePut(value="products", key="#product.id") 
public Product update(Product product) { 
    return this.productRepository.save(product); 
} 

@Override 
@CacheEvict(value="products", key="#id") 
public void delete(Integer id) { 
    this.productRepository.delete(id); 
} 

Vorrei sapere se è possibile aggiorna/cancella l'oggetto che si trova nella cache attraverso lo key="#root.target.PRODUCTS", sarebbe 100 con il Prodotto aggiornato o 499 se il Prodotto è stato cancellato.

Il mio punto è, voglio evitare i seguenti:

@Override 
@CachePut(value="products", key="#product.id") 
@CacheEvict(value="products", key="#root.target.PRODUCTS") 
public Product update(Product product) { 
    return this.productRepository.save(product); 
} 

@Override 
@Caching(evict={ 
     @CacheEvict(value="products", key="#id"), 
     @CacheEvict(value="products", key="#root.target.PRODUCTS") 
}) 
public void delete(Integer id) { 
    this.productRepository.delete(id); 
} 

Non voglio chiamare di nuovo i 500 o 499 prodotti da memorizzare nella cache in key="#root.target.PRODUCTS"

è possibile fare questo? Come?

Grazie in anticipo.

risposta

0

Anche se non vedo un modo semplice, ma è possibile ignorare la funzionalità cache Ehcache fornendo cache decorator. Molto probabilmente si vorrebbe usare EhcahceDecoratorAdapter, per migliorare le funzioni utilizzate dai metodi put e evict EhCacheCache.

5

La memorizzazione nella cache utilizzando l'astrazione di memorizzazione nella cache è un duplicato di ciò che sta facendo il sistema di caching sottostante. E poiché questo è un duplicato, si scopre che è necessario ricorrere a qualche tipo di duplicazione nel proprio codice in un modo o nell'altro (la chiave duplicata per il set è la rappresentazione ovvia di ciò). E poiché c'è una duplicazione, devi sincronizzare lo stato in qualche modo

Se hai davvero bisogno di accedere all'intero insieme e ai singoli elementi, allora dovresti probabilmente usare una scorciatoia per la gamba più facile. Innanzitutto, dovresti assicurarti che la cache contenga tutti gli elementi che non sono qualcosa di ovvio. Lontano da questo in realtà. Considerando che avete:

//EhCacheCache cache = (EhCacheCache) cacheManager.getCache("products"); 


@Override 
public Set<Product> findAll() { 
    Ehcache nativeCache = cache.getNativeCache(); 
    Map<Object, Element> elements = nativeCache.getAll(nativeCache.getKeys()); 
    Set<Product> result = new HashSet<Product>(); 
    for (Element element : elements.values()) { 
     result.add((Product) element.getObjectValue()); 
    } 
    return Collections.unmodifiableSet(result); 
} 

Il risultato elements è in realtà una mappa caricata pigro così una chiamata a values() può generare un'eccezione. Potresti voler passare sopra le chiavi o qualcosa del genere.

È necessario ricordare che l'astrazione di memorizzazione nella cache semplifica l'accesso all'infrastruttura di caching sottostante e non la sostituisce in alcun modo: se si dovesse utilizzare direttamente l'API, è probabile che ciò si debba fare in qualche modo.

Ora, possiamo mantenere la conversione su SPR-12036 se credete di poter migliorare l'astrazione di memorizzazione nella cache in quell'area. Grazie!

+0

Grazie Stephane, sto andando a mantenere la conversazione attraverso JIRA. –

1

Penso che qualcosa di simile potrebbe funzionare ... In realtà è solo una variazione se la risposta di "Stéphane Nicoll", ma può essere utile per qualcuno. Scrivo proprio qui e non l'ho verificato in IDE, ma qualcosa di simile funziona nel mio Progetto.

  1. Override CacheResolver:

    @Cacheable(value="products", key="#root.target.PRODUCTS", cacheResolver = "customCacheResolver") 
    
  2. implementare il proprio risolutore cache, che ricerca "dentro" si memorizzati nella cache oggetti e fare il lavoro in là

    public class CustomCacheResolver implements CacheResolver{ 
        private static final String CACHE_NAME = "products"; 
        @Autowired(required = true) private CacheManager cacheManager; 
    
    @SuppressWarnings("unchecked") 
    @Override 
    public Collection<? extends Cache> resolveCaches(CacheOperationInvocationContext<?> cacheOperationInvocationContext) { 
        // 1. Take key from query and create new simple key 
        SimpleKey newKey; 
        if (cacheOperationInvocationContext.getArgs().length != null) { //optional 
        newKey = new SimpleKey(args); //It's the key of cached object, which your "@Cachable" search for   
        } else { 
        //Schould never be... DEFAULT work with cache if something wrong with arguments 
        return new ArrayList<>(Arrays.asList(cacheManager.getCache(CACHE_NAME))); 
        } 
    
        // 2. Take cache 
        EhCacheCache ehCache = (EhCacheCache)cacheManager.getCache(CACHE_NAME); //this one we bringing back     
        Ehcache cache = (Ehcache)ehCache.getNativeCache(); //and with this we working   
        // 3. Modify existing Cache if we have it 
        if (cache.getKeys().contains(newKey) && YouWantToModifyIt) { 
        Element element = cache.get(key); 
        if (element != null && !((List<Products>)element.getObjectValue()).isEmpty()) { 
        List<Products> productsList = (List<Products>)element.getObjectValue(); 
        // ---**--- Modify your "productsList" here as you want. You may now Change single element in this list.     
        ehCache.put(key, anfragenList); //this method NOT adds cache, but OVERWRITE existing        
        // 4. Maybe "Create" new cache with this key if we don't have it 
        } else { 
        ehCache.put(newKey, YOUR_ELEMENTS); 
        } 
        return new ArrayList<>(Arrays.asList(ehCache)); //Bring all back - our "new" or "modified" cache is in there now... 
    } 
    

Read more su CRUD di EhCache: EhCache code samples

Spero che aiuti. E mi dispiace per il mio inglese :(

Problemi correlati