2017-03-09 59 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