2017-03-09 1 views
0

Je suis le guide de mise en cache de printemps ici - https://spring.io/guides/gs/caching/, mais le mien est un objet un peu complexe.Retour de l'objet imbriqué dans le cache au printemps 4

Pour mon cas d'utilisation, j'ai aussi un champ Author. Voici ma classe complète Book. Maintenant, j'ai ajouté une autre méthode pour récupérer le livre par l'auteur (en supposant qu'un seul livre est retourné). Voici mon 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); 
     } 
    } 
} 

Maintenant, je me demandais si je pouvais récupérer les Book instances du cache en regardant le Author.id dans le cache.

Voici mon exécution et le comportement attendu.

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 

Y at-il un moyen de le faire ou j'aurais besoin d'un autre cache à cet effet?

Répondre

0

Vous n'avez pas besoin d'un autre cache. Spécifiez simplement dans votre méthode getByAuthorId que vous voulez également mettre cette méthode en cache. Spring va créer une entrée dans le cache avec l'identifiant de l'auteur clé et la valeur Book chaque fois que vous appelez cette méthode si elle n'existe pas déjà. Ajoutez simplement @Cacheable("books") à votre méthode getByAuthorId. Maintenant, dans votre cache books, vous aurez des entrées avec les clés isbn et les clés author.id qui correspondent à Books.

En réponse à Ce que je suis à la recherche est si l'instance a été ajouté à cache lorsque getByIsbn() a été appelé, je veux être en mesure d'utiliser la même instance quand je l'appelle getBookByAuthorId() la seule solution que je peux penser de si vous ajoutez manuellement l'entrée à votre cache comme:

@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

Je l'ai fait. Cependant, cela ne fonctionne pas comme prévu. Ce que je cherche, c'est si l'instance a été ajoutée au cache quand 'getByIsbn()' a été appelée, je veux être capable d'utiliser la même instance quand j'appelle 'getBookByAuthorId()'. – divinedragon

+0

OK, maintenant. Je ne pense pas que ce soit possible, car Spring s'appuie sur la méthode input pour générer une clé cache, et il n'y a aucun moyen de corréler l'isbn avec author.id – artemisian

+0

@divinedragon s'il vous plaît vérifier mon edit – artemisian