【问题标题】:Returning the nested object in the cache in Spring 4在 Spring 4 中返回缓存中的嵌套对象
【发布时间】:2017-03-09 13:43:49
【问题描述】:

我在这里遵循 Spring 缓存指南 - https://spring.io/guides/gs/caching/,但我的对象有点复杂。

对于我的用例,我也有一个 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

有没有办法做到这一点,或者我需要另一个缓存来实现这个目的?

【问题讨论】:

    标签: java spring caching spring-boot spring-cache


    【解决方案1】:

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

    所以现在在您的 books 缓存中,您将拥有映射到 Books 的带有 isbn 键和 author.id 键的条目。

    作为回应我能想到的解决方案是,如果您手动将条目添加到缓存中,例如:

    @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;
        }
    
        // ......
    }
    

    【讨论】:

    • 我做到了。但是,它不像我预期的那样工作。我正在寻找的是,如果在调用 getByIsbn() 时将实例添加到缓存中,我希望在调用 getBookByAuthorId() 时能够使用相同的实例。
    • 好的,现在知道了。我不认为这是可能的,因为 Spring 依赖于方法输入 args 来生成缓存键,并且没有办法将 isbn 与 author.id 相关联
    • 没有按预期工作。无论如何,我认为没有直接的方法可以做到这一点。
    猜你喜欢
    • 2019-08-08
    • 2021-09-04
    • 1970-01-01
    • 2021-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    相关资源
    最近更新 更多