2017-03-09 58 views
0

我正在按照Spring的指导进行缓存 - https://spring.io/guides/gs/caching/,但我的是一个有点复杂的对象。在Spring 4中返回缓存中的嵌套对象

对于我的用例,我也有一个Author字段。这是我整个Book班。

public class Book { 

    private String isbn; 
    private String title; 
    private Author author; 

    public Book(String isbn, String title, Author author) { 
     this.isbn = isbn; 
     this.title = title; 
     this.author = author; 
    } 

    public String getIsbn() { 
     return isbn; 
    } 

    public void setIsbn(String isbn) { 
     this.isbn = isbn; 
    } 

    public String getTitle() { 
     return title; 
    } 

    public void setTitle(String title) { 
     this.title = title; 
    } 

    public Author getAuthor() { 
     return author; 
    } 

    public void setAuthor(Author author) { 
     this.author = author; 
    } 

    @Override 
    public String toString() { 
     return String.format("Book{isbn='%s',title='%s',author=%s}", isbn, title, author); 
    } 
} 

现在,我添加了另一种方法来通过作者id(假设只返回一本书)获取书籍。这是我的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); 
     } 
    } 
} 

,我在想,如果我可以在缓存中查找该Author.id获取从缓存中Book实例。

这是我的执行和预期的行为。

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 

有没有办法做到这一点还是我需要另一个缓存为这个目的是什么?

回答

0

你不需要另一个缓存。只需在你的getByAuthorId方法中指定你想缓存该方法。如果每次调用该方法(如果它不存在),Spring将在缓存中创建一个关键作者ID和值Book的条目。只需将@Cacheable("books")添加到getByAuthorId方法。

因此,现在在您的books缓存中,您将拥有包含映射到Books的isbn键和author.id键的条目。

针对我所寻找的,如果该实例加入时getByIsbn()被调用缓存中,我希望能够使用相同的情况下,当我打电话getBookByAuthorId()唯一的解决办法我能想到的是如果您手动添加条目到您的缓存中,例如:

@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

我做到了。但是,它不像我所期望的那样工作。我在看的是如果在调用'getByIsbn()'时将实例添加到缓存中,我希望在调用'getBookByAuthorId()'时能够使用同一个实例。 – divinedragon

+0

好的,现在就明白了。我不认为这是可能的,因为Spring依靠方法输入参数来生成缓存键,并且没有办法将isbn与author.id – artemisian

+0

@divinedragon请检查我的编辑 – artemisian