2016-12-29 3 views
1

Ich benutze Spring Boot mit Spring Cache. Ich habe eine Methode, die eine Liste von IDs gegeben, um eine Liste von Food zurückgibt, die mit diesen IDs entsprechen:Wie kann ich eine Datenbankabfrage mit dem Operator "IN" zwischenspeichern?

public List<Food> get(List<Integer> ids) { 
    return "select * from FOOD where FOOD_ID in ids"; // << pseudo-code 
} 

Ich möchte die Ergebnisse von id zwischenzuspeichern. Stellen Sie sich vor, dass ich tun:

List<Food> foods = get(asList(1, 5, 7)); 

und dann:

List<Food> foods = get(asList(1, 5)); 

Ich möchte Food mit der ID 1 und Food mit id 5 aus dem Cache abgerufen werden. Ist es möglich?

Ich weiß, ich kann wie ein Verfahren tun:

@Cacheable(key = "id") 
public Food getById(id){ 
    ... 
} 

und die IDs Liste durchlaufen und es jedes Mal nennen, aber in diesem Fall, den ich nicht nutzen von IN SQL-Operator, nicht wahr? Vielen Dank.

+0

tun nur 'return ids.stream() Karte (Service :: getById) .collect (Collectors.toList()) '0 –

Antwort

1

Das Schlüsselattribut von Cacheable verwendet einen SpEL-Ausdruck, um den Cache-Schlüssel zu berechnen. So sollten Sie in der Lage sein, etwas zu tun, wie

@Cacheable(key = "#ids.stream().map(b -> Integer.toString(b)).collect(Collectors.joining(","))) 

Dies würde die ids erfordern immer in der gleichen Reihenfolge würde

https://docs.spring.io/spring/docs/current/spring-framework-reference/html/cache.html#cache-annotations-cacheable-key

Eine bessere Option zu sein, eine Klasse zu erstellen, zu wickeln um Ihre IDs, die in der Lage wären, den Cacheschlüssel für Sie oder irgendeine Art von Dienstprogrammklasse zu erzeugen.


Eine andere mögliche Lösung ohne @Cacheable wäre der Cache-Manager in die Klasse wie zu injizieren:

@Autowired 
private CacheManager cacheManager; 

Sie dann die Lebensmittel-Cache aus dem Cache-Manager

namentlich
Cache cache = cacheManager.getCache('cache name'); 
abrufen

dann können Sie Ihre Methode anpassen, um die Liste der IDs aufzunehmen und manuell die Werte aus dem Cache

hinzuzufügen und abzurufen 10

Sie werden höchstwahrscheinlich immer noch nicht in der Lage sein, die SQL IN-Klausel zu verwenden, aber Sie behandeln zumindest die Iteration innerhalb der Methode und nicht überall, wo diese Methode aufgerufen wird, und nutzen den Cache wann immer möglich.

public List<Food> get(List<Integer> ids) { 
    List<Food> result = new ArrayList<>(); 

    for(Integer id : ids) { 
     // Attempt to fetch from cache 
     Food food = cache.get(id); 

     if (food == null) { 
      // Fetch from DB 
      cache.put(id, food); 
     } 

     result.add(food); 
    } 

    return result; 
} 

Relevante Javadocs.

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/CacheManager.html

http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/cache/Cache.html

+0

Danke. Aber in diesem Fall würde das Beispiel in meiner Frage nicht funktionieren, weil der Schlüssel in beiden Fällen nicht derselbe ist. Ich möchte jedes einzelne Essen zwischenspeichern, nicht das ganze Set. –

+0

Okay, in diesem Fall, wenn Sie '@ Cacheable' verwenden möchten, müssen Sie nur die Aufrufe durchlaufen, damit Ihre Methode eine einzelne ID annimmt und ein einzelnes Ergebnis zurückgibt. – kgengler

+0

Ohne @Cacheable können Sie den CacheManager einsperren und eine Instanz des Caches verwenden, um die Cachewerte manuell zu setzen und abzurufen – kgengler

Verwandte Themen