1. ホーム
  2. java

[解決済み] Caffeineキャッシュがデータベースクエリから保護されない

2022-02-27 08:08:31

質問

Spring BootアプリでCaffeineキャッシュの基本的なセットアップを実装しています。以下、設定とサービスメソッドを @Cachable . 残念ながら、このメソッドを呼び出すたびにデータベースへの問い合わせが発生し、キャッシュへの新しい入力(同じキーで)が発生します。

キャッシュの内容を含むデバッグ結果

    @Cacheable(cacheNames = {"pic"})
    public PictureModel loadPictureById(String id) {
        var loadedInstance = pictureRepo.findById(id).orElseThrow(() -> new CustomNotFoundException(PictureModel.class));
        loadedInstance.setBody(pictureCompressor.decompressBytes(loadedInstance.getBody()));
        return loadedInstance;
    }

コンフィギュレーションです。

@EnableCaching
@Configuration
public class CaffeineConfig {
    @Bean
    public CacheManager cacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager("pic");
        cacheManager.setCaffeine(caffeineCacheBuilder());
        return cacheManager;
    }

    Caffeine <Object, Object> caffeineCacheBuilder() {
        return Caffeine.newBuilder()
                .initialCapacity(100)
                .maximumSize(500)
                .expireAfterAccess(10, TimeUnit.MINUTES)
                .weakKeys()
                .recordStats();
    }
}

3回ヒットした後のデータベースクエリ。

Hibernate: 
    select
        picturemod0_.id as id1_10_0_,
        picturemod0_.account_id as account_5_10_0_,
        picturemod0_.body as body2_10_0_,
        picturemod0_.name as name3_10_0_,
        picturemod0_.public_platform_id as public_p6_10_0_,
        picturemod0_.service_type_id as service_7_10_0_,
        picturemod0_.type as type4_10_0_ 
    from
        image picturemod0_ 
    where
        picturemod0_.id=?
Hibernate: 
    select
        picturemod0_.id as id1_10_0_,
        picturemod0_.account_id as account_5_10_0_,
        picturemod0_.body as body2_10_0_,
        picturemod0_.name as name3_10_0_,
        picturemod0_.public_platform_id as public_p6_10_0_,
        picturemod0_.service_type_id as service_7_10_0_,
        picturemod0_.type as type4_10_0_ 
    from
        image picturemod0_ 
    where
        picturemod0_.id=?
Hibernate: 
    select
        picturemod0_.id as id1_10_0_,
        picturemod0_.account_id as account_5_10_0_,
        picturemod0_.body as body2_10_0_,
        picturemod0_.name as name3_10_0_,
        picturemod0_.public_platform_id as public_p6_10_0_,
        picturemod0_.service_type_id as service_7_10_0_,
        picturemod0_.type as type4_10_0_ 
    from
        image picturemod0_ 
    where
        picturemod0_.id=?

私は1つのデータベースクエリと他のヒットがキャッシュによって提供されることを実現したい。

どのように解決するのですか?

削除する weakKeys() を追加してください。 CaffeineConfig .

から weakKeys() のドキュメントを参照してください。

警告: このメソッドを使用すると、結果のキャッシュはキーの等価性を判断するために同一性 (==) 比較を使用します。

あなたの設定では、キーはObjectとして計算されていますが weakKeys() と比較しています。 == そのため、キーが不一致となり、キャッシュミスが発生します。