javaspringspring-cachecaffeine

Caffeine cache does not prevent from database queries


I've implemented basic set up of Caffeine cache in Spring Boot app. Below you will find configuration and service method annotated with @Cachable. Unfortunately every call for this method generates database query and new input to cache (with same key):

Debug result with cache content

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

Configuration:

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

Database queries after three hits:

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=?

I would like to achieve one database query and other hits to be served by cache.


Solution

  • Remove weakKeys() from your CaffeineConfig.

    From weakKeys() documentation,

    Warning: when this method is used, the resulting cache will use identity (==) comparison to determine equality of keys.

    In your config , you are computing keys as Object but weakKeys() is comparing them with ==, so keys are matched as not eqaul and cache miss is happening.