Search code examples
spring-bootcachingredis

Get value from cache if it exists, else from DB, but don't write back to cache


I have a use case, wherein, if a value exists in the cache, I'll retrieve from it, else, I'll query the DB, and provide the response, but don't want the result to be cached.

I went through different annotations - https://www.baeldung.com/spring-cache-tutorial, but could not find anyone sufficing the use case.

Very simply, I want to do the following:

if value exists in cache
  return value
else
  return valueFromDB()

Since this code is for production services, I want to use annotations, and keep customization as minimum as possible.

Can someone guide me of a useful annotation for the case?


Solution

  • Yes, starting with gs-spring-caching/complete, this:

    @Cacheable(cacheNames = "books", unless = "true") // !!!
    public Book getSpecial(String isbn) { // ... same as sample
    }
    

    ..gives us desired behavior:

    • "books" cache is always issued,
    • never written back,
    • and "evicts" nothing.

    Adjusting:

    • BookRepository (interface)
    • With a modified test (AppRunner):
      @Override
      public void run(String... args) throws Exception {
            logger.info(".... Fetching books");
            // populates cache with 1 book:
            logger.info("isbn-1234 -->" + bookRepository.getByIsbn("isbn-1234"));
            // always issues, never writes back to - cache:
            logger.info("isbn-1234 -->" + bookRepository.getSpecial("isbn-1234"));
            logger.info("isbn-4567 -->" + bookRepository.getSpecial("isbn-4567"));
            logger.info("isbn-1234 -->" + bookRepository.getSpecial("isbn-1234"));
            logger.info("isbn-4567 -->" + bookRepository.getSpecial("isbn-4567"));
            logger.info("isbn-1234 -->" + bookRepository.getSpecial("isbn-1234"));
            logger.info("isbn-1234 -->" + bookRepository.getSpecial("isbn-1234"));
      }
      
    • add logging to "slow service"

    ..we can verify:

    2022-10-07 14:04:24.917  INFO 7...Runner: .... Fetching books
    2022-10-07 14:04:24.933  INFO 7...itory:  not from cache!
    2022-10-07 14:04:27.934  INFO 7...Runner: isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
    2022-10-07 14:04:27.937  INFO 7...Runner: isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
    2022-10-07 14:04:27.939  INFO 7...itory:  not from cache!
    2022-10-07 14:04:31.042  INFO 7...Runner: isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
    2022-10-07 14:04:31.044  INFO 7...Runner: isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
    2022-10-07 14:04:31.045  INFO 7...itory:  not from cache!
    2022-10-07 14:04:34.066  INFO 7...Runner: isbn-4567 -->Book{isbn='isbn-4567', title='Some book'}
    2022-10-07 14:04:34.067  INFO 7...Runner: isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
    2022-10-07 14:04:34.068  INFO 7...Runner: isbn-1234 -->Book{isbn='isbn-1234', title='Some book'}
    


    condition="false" gives us "no cache" behavior (so makes no sense on that annotation).

    @Cacheable-javadoc