2014-07-24 21 views
6

ich mit Frühling und ehcache arbeiteteWie Aktualisierung/entfernt ein Element bereits innerhalb einer Sammlung von Gegenständen im Cache

Ich habe die folgende Methode

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

Ich habe andere Methoden arbeiten mit @Cacheable und @CachePut und @CacheEvict. Jetzt

, stellen die Datenbank zurückgibt 100 Produkte und sie werden durch key="#root.target.PRODUCTS" zwischengespeichert, dann andere Methode wäre Einsatz - update - gelöscht ein Element in die Datenbank. Daher sind die Produkte, die durch die key="#root.target.PRODUCTS" zwischengespeichert werden, nicht mehr dieselben wie die Datenbank.

Ich meine, überprüfen Sie die beiden folgenden zwei Methoden, sie in der Lage sind, ein Element zu aktualisieren/löschen, und dass gleiche Element in der anderen key="#root.target.PRODUCTS"

gecached
@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); 
} 

Ich möchte wissen, wenn möglich Aktualisieren/löschen Sie den im Cache befindlichen Artikel über die key="#root.target.PRODUCTS", es wäre 100 mit dem Produkt aktualisiert oder 499, wenn das Produkt gelöscht wurde.

Mein Punkt ist, ich möchte vermeiden, die folgenden:

@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); 
} 

Ich will nicht wieder rufen die 500 oder 499 Produkte in den

key="#root.target.PRODUCTS"

zwischengespeichert werden dies möglich ist zu tun? Wie?

Vielen Dank im Voraus.

Antwort

0

Obwohl ich keine einfache Möglichkeit sehe, aber Sie können Ehcache-Cache-Funktionalität überschreiben, indem Sie cache decorator liefern. Höchstwahrscheinlich möchten Sie verwenden, um Funktionen zu verbessern, die von EhCacheCache Put- und Evict-Methoden verwendet werden.

5

Caching der Sammlung mit der Caching-Abstraktion ist ein Duplikat dessen, was das zugrundeliegende Caching-System tut. Und da es sich um ein Duplikat handelt, müssen Sie in Ihrem eigenen Code auf irgendeine Art und Weise auf Duplikate zurückgreifen (der doppelte Schlüssel für den Satz ist die offensichtliche Darstellung davon). Und da es Duplizierung gibt, müssen Sie den Status irgendwie synchronisieren

Wenn Sie wirklich auf den ganzen Satz und einzelne Elemente zugreifen müssen, dann sollten Sie wahrscheinlich eine Abkürzung für das einfachste Bein verwenden. Zuerst sollten Sie sicherstellen, dass Ihr Cache alle Elemente enthält, was nicht offensichtlich ist. Ganz im Gegenteil. Erwägen Sie haben die:

//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); 
} 

Das elements Ergebnis tatsächlich eine faule geladene Karte ist so ein Aufruf an values() kann eine Ausnahme auslösen. Vielleicht möchten Sie die Tasten oder etwas überlappen.

Sie müssen sich daran erinnern, dass die Caching-Abstraktion den Zugriff auf die zugrunde liegende Caching-Infrastruktur erleichtert und keinesfalls ersetzt: Wenn Sie die API direkt verwenden müssten, müssten Sie dies wahrscheinlich irgendwie tun.

Jetzt können wir die Konvertierung auf SPR-12036 beibehalten, wenn Sie glauben, dass wir die Caching-Abstraktion in diesem Bereich verbessern können. Vielen Dank!

+0

Danke Stephane, ich werde das Gespräch durch JIRA halten. –

1

Ich denke so etwas sollte funktionieren ... Eigentlich ist es nur eine Variante, wenn "Stéphane Nicoll" natürlich antwortet, aber es kann für jemanden nützlich sein. Ich schreibe es hier und habe es nicht in der IDE überprüft, aber etwas Ähnliches funktioniert in meinem Projekt.

  1. Aufschalten CacheResolver:

    @Cacheable(value="products", key="#root.target.PRODUCTS", cacheResolver = "customCacheResolver") 
    
  2. Implementieren Sie Ihre eigenen Cache-Resolver, der

    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... 
    } 
    
    da drin "innen" Sie Elemente zwischengespeichert und die Arbeit zu suchen

Lesen Sie mehr über CRUD von EhCache: EhCache code samples

Hoffe es hilft. Und Entschuldigung für mein Englisch :(