2015-01-14 17 views
9

私は、データベースクエリを改善するために、スプリング・キャッシュを使用して、次のように正常に動作されています:春の起動時に@Cacheを読み込む方法は?

@Bean 
public CacheManager cacheManager() { 
    return new ConcurrentMapCacheManager("books"); 
} 

@Cacheable("books") 
public Book getByIsbn(String isbn) { 
    return dao.findByIsbn(isbn); 
} 

しかし、今、私は起動時にフルブックキャッシュを事前入力します。つまり、私はdao.findAll()に電話し、すべての値をキャッシュに入れたいと思っています。このルーチンは定期的にスケジュールされるだけである。

しかし、@Cacheableを使用すると、明示的にキャッシュにデータを入力できますか?

答えて

7

以前と同じようにキャッシュを使用し、キャッシュを更新するスケジューラを追加すると、コードスニペットは以下のようになります。

@Service 
public class CacheScheduler { 
    @Autowired 
    BookDao bookDao; 
    @Autowired 
    CacheManager cacheManager; 

    @PostConstruct 
    public void init() { 
     update(); 
     scheduleUpdateAsync(); 
    } 

    public void update() { 
     for (Book book : bookDao.findAll()) { 
      cacheManager.getCache("books").put(book.getIsbn(), book); 
     } 
    } 
} 

ていることを確認してくださいあなたのKeyGenerator(デフォルトとして)一つのパラメータのためのオブジェクトを返します。あるいは、putToCacheメソッドをBookServiceに公開して、cacheManagerを直接使用しないようにしてください。

@CachePut(value = "books", key = "#book.isbn") 
public Book putToCache(Book book) { 
    return book; 
} 
3

スタートアップ時にメモリ内のブックのすべてのインスタンスを必要とする場合は、自分でバッファに保存するよりも必要です。 findAll()メソッドを使用してそれらをキャッシュに格納すると、findAll()に@Cacheableを注釈する必要があります。次に、起動時にfindAll()を呼び出さなければなりません。 しかし、findAll()を呼び出すときに対応するインスタンスがキャッシュに置かれていても、getByIsbn(String isbn)を呼び出すとキャッシュにアクセスするわけではありません。 実際には、ehcacheはメソッドの戻り値をメソッドが呼び出されたときにkeyが計算されるキーと値のペアとしてキャッシュするため、したがって、返される型が同じではなく、さらにすべてのインスタンスに対してキーが決して一致しないため、findAll()の戻り値とgetByIsbn(String)の戻り値がどのように一致するかわかりません。

0

別のBean BookCacheInitialzer

Autowire BookCacheInitialzer 擬似コードのPostConstruct方法で

BookCacheInitialzer

における現在の豆BookServiceを追加

そして

class BookService { 
    @Cacheable("books") 
    public Book getByIsbn(String isbn) { 
     return dao.findByIsbn(isbn); 
    } 

    public List<Book> books; 

    @Cacheable("books") 
    public Book getByIsbnFromExistngBooks(String isbn) { 
     return searchBook(isbn, books); 
    } 

ような何かを行うことができ}

class BookCacheInitialzer { 

@Autowired 
BookService service 

@PostConstruct 
public void initialize() { 
     books = dao.findAll(); 
    service.books = books; 
    for(Book book:books) { 
     service.getByIsbnFromExistngBooks(book.getIsbn()); 
    } 

} 

}

+0

はい、これはオプションですが、すべてのエントリの起動時にn回DBにぶつかっているため、パフォーマンスは非常に悪いです。さらに、findAll()によってすべての書籍がすでにあるので、何とか冗長です。だから私はdbに別の往復なしでキャッシュにこれらの本を得る方法を探しています。 – membersound

+0

次に、何かをすることができます –

+0

それに応じてsolnを編集しました。 –

1
オリビエとして

を使用すると、それらは後で個別にアクセスすることができるように、キャッシュ内のすべてのオブジェクトをロードすることはできませんのfindAllと@cacheable表記を使用して、単一のオブジェクトとしての機能のばねキャッシュ出力するので、指定されました。

キャッシュ内のすべてのオブジェクトをロードできる方法の1つは、使用中のキャッシュソリューションが起動時にすべてのオブジェクトをロードする方法を提供する場合です。たとえばNCache/TayzGridのようなソリューションでは、構成可能なキャッシュスタートアップローダーを使用してオブジェクトを起動するときにキャッシュを読み込むことができるキャッシュスタートアップローダー機能を提供しています。

2

オプションは、起動時にキャッシュを設定するためにCommandLineRunnerを使用することです。公式CommandLineRunnerドキュメントから

、それは次のとおりです。

インタフェースは、Beanが実行それはSpringApplication内に含まれている必要があるときことを示すために使用しました。

したがって、使用可能なすべての書籍のリストを取得してから、CacheManagerを使用してブックキャッシュにデータを挿入するだけです。

@Component 
public class ApplicationRunner implements CommandLineRunner { 
    @Autowired 
    private BookDao dao; 

    @Autowired 
    private CacheManager cacheManager; 

    @Bean 
    public CacheManager cacheManager() { 
     return new ConcurrentMapCacheManager("books"); 
    } 

    @Override 
    public void run(String... args) throws Exception { 

     List<Book> results = dao.findAll(); 

     results.forEach(book -> 
      cacheManager.getCache("books").put(book.getId(), book)); 
    } 
} 
関連する問題