Miłosz
Miłosz

Reputation: 27

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.

Upvotes: 0

Views: 1509

Answers (1)

Shawrup
Shawrup

Reputation: 2754

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.

Upvotes: 3

Related Questions