2017-03-09 3 views
0

Ich bin der Federführung zum Zwischenspeichern hier - https://spring.io/guides/gs/caching/, aber meins ist ein bisschen komplexes Objekt.Zurückgeben des verschachtelten Objekts im Cache im Frühjahr 4

Für meinen Anwendungsfall habe ich auch ein Author Feld. Hier ist meine gesamte Book Klasse.

Jetzt habe ich eine andere Methode hinzugefügt, Buch nach Autor-ID zu holen Hier ist meine SimpleBookRepository.

@Component 
public class SimpleBookRepository implements BookRepository { 

    private List<Book> books; 

    public SimpleBookRepository() { 
     books = new ArrayList<>(); 
     books.add(new Book("1234", "Some book", new Author(1, "Author1"))); 
     books.add(new Book("4567", "Some another book", new Author(2, "Author2"))); 
    } 

    @Override 
    @Cacheable("books") 
    public Book getByIsbn(String isbn) { 
     simulateSlowService(); 
     return books.stream().filter(o -> o.getIsbn().equals(isbn)).findFirst().orElse(null); 
    } 

    @Override 
    public Book getByAuthorId(int id) { 
     simulateSlowService(); 
     return books.stream().filter(o -> o.getAuthor().getId() == id).findFirst().orElse(null); 
    } 

    // Don't do this at home 
    private void simulateSlowService() { 
     try { 
      long time = 1000L; 
      Thread.sleep(time); 
     } catch (InterruptedException e) { 
      throw new IllegalStateException(e); 
     } 
    } 
} 

Nun, ich frage mich, ob ich durch Nachschlagen der Author.id im Cache die Book Instanzen aus dem Cache holen kann.

Hier ist meine Ausführung und erwartetes Verhalten.

logger.info(".... Fetching books"); 
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("1234")); // Gets the original object 
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("4567")); // Gets the original object 
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("1234")); // Should fetch from cache - WORKS FINE 
logger.info("isbn-4567 -->" + bookRepository.getByIsbn("4567")); // Should fetch from cache - WORKS FINE 
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("1234")); // Should fetch from cache - WORKS FINE 
logger.info("isbn-1234 -->" + bookRepository.getByIsbn("1234")); // Should fetch from cache - WORKS FINE 

logger.info(".... Fetching books by author"); 
logger.info("author-1 -->" + bookRepository.getByAuthorId(1)); // Should fetch from cache - NOT WORKING 
logger.info("author-2 -->" + bookRepository.getByAuthorId(2)); // Should fetch from cache - NOT WORKING 
logger.info("author-1 -->" + bookRepository.getByAuthorId(1)); // Should fetch from cache - NOT WORKING 
logger.info("author-2 -->" + bookRepository.getByAuthorId(2)); // Should fetch from cache - NOT WORKING 
logger.info("author-1 -->" + bookRepository.getByAuthorId(1)); // Should fetch from cache - NOT WORKING 
logger.info("author-1 -->" + bookRepository.getByAuthorId(1)); // Should fetch from cache - NOT WORKING 

Gibt es eine Möglichkeit, dies zu tun, oder würde ich einen anderen Cache für diesen Zweck benötigen?

Antwort

0

Sie benötigen keinen weiteren Cache. Geben Sie in Ihrer Methode "getByAuthorId" an, dass Sie diese Methode ebenfalls zwischenspeichern möchten. Spring erstellt bei jedem Aufruf dieser Methode einen Eintrag im Cache mit der Schlüssel-Autor-ID und dem Wert "Buch", wenn diese Methode noch nicht existiert. Fügen Sie einfach die @Cacheable("books") Ihrer getByAuthorId-Methode hinzu.

So jetzt in Ihrem books Cache haben Sie Einträge mit Isbn-Schlüssel und Autor.ID-Schlüssel, die Bücher zuordnen.

Als Antwort auf Was ich suche ist, wenn die Instanz zu Cache hinzugefügt wurde, als getByIsbn() aufgerufen wurde, möchte ich die gleiche Instanz verwenden können, wenn ich getBookByAuthorId() aufrufen die einzige Lösung, die ich denken kann, Wenn Sie den Eintrag manuell zu Ihrem Cache hinzufügen, wie zum Beispiel:

@Component 
public class SimpleBookRepository implements BookRepository { 

    // inject this bean 
    private CacheManager cacheManager; 

    @Override 
    @Cacheable("books") 
    public Book getByIsbn(String isbn) { 
     simulateSlowService(); 
     Book b = books.stream().filter(o -> o.getIsbn().equals(isbn)).findFirst().orElse(null); 

     if (b != null && b.getAuthor() != null && b.getAuthor().getId() != null) { 
      Cache cache = cacheManager.getCache("books"); 
      cache.put(b.getAuthor().getId(), b); 
     } 

     return b; 
    } 

    // ...... 
} 
+0

habe ich das getan. Es funktioniert jedoch nicht wie ich es erwarte. Was ich suche ist, wenn die Instanz zum Cache hinzugefügt wurde, als 'getByIsbn()' aufgerufen wurde, möchte ich in der Lage sein, dieselbe Instanz zu verwenden, wenn ich 'getBookByAuthorId() 'aufruft. – divinedragon

+0

OK, hab es jetzt. Ich glaube nicht, dass das möglich ist, da Spring auf die Methode args angewiesen ist, um einen Cache-Schlüssel zu generieren, und es gibt keine Möglichkeit, den isbn mit author.id zu korrelieren. – artemisian

+0

@divinedragon Bitte überprüfen Sie meine Bearbeitung – artemisian