The product list is the shop's busiest page, and it rarely changes, so running the same query for every visitor is wasted work. A cache keeps an answer you already worked out, so you can give it again without the work.
The simplest cache is a HashMap: its keys name what is remembered, its values are the remembered answers. Look for the key first; if it's there, return the remembered answer; if not, do the work and store the result. Here is the idea on another value, squares of numbers:
private final Map<Integer, Integer> squares = new HashMap<>();
int square(int n) {
if (squares.containsKey(n)) {
return squares.get(n);
}
int result = n * n;
squares.put(n, result);
return result;
}
The first call fills the cache, every later call reads it. Count the queries to prove it: two lists, one query. Only GET /products uses the cache, so GET /products/1 still asks the database. Your code must give these answers, in this order:
GET /products → 200 [{"category": "kitchen", "id": 1, "name": "Mug", "price": 12, "stock": 10}, … 8 products]
GET /debug/queries → 200 {"queries": 1}
GET /products → 200 [the same 8 products]
GET /debug/queries → 200 {"queries": 1}
GET /products/1 → 200 {"category": "kitchen", "id": 1, "name": "Mug", "price": 12, "stock": 10}
GET /debug/queries → 200 {"queries": 2}
The cache lives in the app's memory, not in the database, so it starts empty each time the app starts.
Your task: below stats, add a field cache, an empty HashMap with String keys and Object values. In getProducts, store rows in cache under the key "products" just before the return, and, at the top, return the remembered list right away when cache has the key "products".
Assignment
Follow the Coding Tutorial to cache the product list, so only the first GET /products runs the query.
Hint
The check must come before the query, or the query has already run. getProducts returns Object, so it can return cache.get("products") just as it is: Spring sends it as JSON.
Free plan: 30 tutor messages. PRO is unlimited.
