Java 在Spring 4中返回缓存中的嵌套对象

Java 在Spring 4中返回缓存中的嵌套对象,java,spring,caching,spring-boot,spring-cache,Java,Spring,Caching,Spring Boot,Spring Cache,我在这里遵循Spring缓存指南,但我的是一个有点复杂的对象 对于我的用例,我还有一个Author字段。这是我的整本书 public class Book { private String isbn; private String title; private Author author; public Book(String isbn, String title, Author author) { this.isbn = isbn;

我在这里遵循Spring缓存指南,但我的是一个有点复杂的对象

对于我的用例,我还有一个
Author
字段。这是我的整本

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);
        }
    }
}

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

您不需要另一个缓存。只需在getByAuthorId方法中指定要缓存该方法的内容。Spring将在缓存中创建一个条目,该条目具有密钥作者id和值Book,只要您每次调用该方法(如果该方法尚不存在)。只需将
@Cacheable(“books”)
添加到getByAuthorId方法中

因此,现在在
书籍
缓存中,您将拥有映射到书籍的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;
    }

    // ......
}

我做到了。然而,它并不像我期望的那样工作。我要看的是,如果在调用
getByIsbn()
时将实例添加到缓存中,我希望在调用
getBookByAuthorId()
时能够使用相同的实例。好的,现在就知道了。我认为这是不可能的,因为Spring依赖于方法输入参数来生成缓存键,并且没有办法将isbn与author关联起来。IDBN没有按预期工作。无论如何,我认为没有直接的方法可以做到这一点。
@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;
    }

    // ......
}