Bird
Raised Fist0
Spring Bootframework~15 mins

@CachePut for updating cache in Spring Boot - Deep Dive

Choose your learning style10 modes available
Overview - @CachePut for updating cache
What is it?
@CachePut is an annotation in Spring Boot used to update the cache with the latest method result every time the method is called. Unlike @Cacheable, which skips method execution if the cache has data, @CachePut always runs the method and then refreshes the cache. This helps keep cached data fresh without skipping the actual method logic. It is mainly used when you want to update cache entries after modifying data.
Why it matters
Without @CachePut, caches can become stale because they only update when data is first requested or explicitly cleared. This can cause users to see outdated information, leading to confusion or errors. @CachePut solves this by ensuring the cache always reflects the latest data after updates, improving application performance and user experience by combining fresh data with fast access.
Where it fits
Before learning @CachePut, you should understand basic caching concepts and the @Cacheable annotation in Spring Boot. After mastering @CachePut, you can explore cache eviction with @CacheEvict and advanced cache configurations like custom key generators and cache managers.
Mental Model
Core Idea
@CachePut always runs the method and updates the cache with its result, ensuring the cache stays fresh after data changes.
Think of it like...
Imagine a bulletin board where you always post the latest news after checking the source, even if the board already has an old notice. You replace the old notice with the new one every time you get an update.
┌───────────────┐       ┌───────────────┐
│ Method Call   │──────▶│ Method Runs   │
└───────────────┘       └───────────────┘
                              │
                              ▼
                     ┌─────────────────┐
                     │ Cache Updated   │
                     │ with New Result │
                     └─────────────────┘
Build-Up - 7 Steps
1
FoundationBasic caching concept in Spring Boot
🤔
Concept: Caching stores method results to speed up repeated calls with the same inputs.
Spring Boot uses annotations like @Cacheable to save method results in a cache. When a method annotated with @Cacheable is called, Spring checks if the result is already cached. If yes, it returns the cached result without running the method again.
Result
Repeated calls with the same inputs return cached results instantly, improving performance.
Understanding caching basics is essential because @CachePut builds on this idea but changes when the cache updates.
2
FoundationDifference between @Cacheable and @CachePut
🤔
Concept: @Cacheable skips method execution if cached data exists; @CachePut always runs the method and updates the cache.
With @Cacheable, if the cache has data, the method is not executed again. With @CachePut, the method runs every time, and its result replaces the cache entry. This means @CachePut is used when you want to refresh the cache after data changes.
Result
You get fresh data in the cache every time the method runs with @CachePut, unlike @Cacheable which may return stale data.
Knowing this difference helps decide when to use @CachePut to keep cache data fresh after updates.
3
IntermediateUsing @CachePut to update cache after data change
🤔Before reading on: Do you think @CachePut prevents method execution if cache exists, or always runs the method? Commit to your answer.
Concept: @CachePut runs the method every time and updates the cache with the new result.
Annotate a method that modifies data with @CachePut and specify the cache name and key. When this method runs, it updates the cache entry with the latest data. For example: @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { // update user in database return user; } This ensures the cache 'users' always has the updated user info.
Result
Cache entries reflect the latest data immediately after updates, avoiding stale cache problems.
Understanding that @CachePut forces method execution and cache update prevents common bugs where cache is not refreshed after data changes.
4
IntermediateCombining @CachePut with @Cacheable for read-write caching
🤔Before reading on: Can you use @CachePut and @Cacheable on the same method? Why or why not? Commit to your answer.
Concept: Use @Cacheable for read methods to cache results and @CachePut for write methods to update cache after changes.
Typically, you use @Cacheable on methods that read data to avoid repeated database calls. Use @CachePut on methods that modify data to update the cache. For example: @Cacheable(value = "users", key = "#id") public User getUser(Long id) { ... } @CachePut(value = "users", key = "#user.id") public User updateUser(User user) { ... } This pattern keeps cache consistent and efficient.
Result
Reads are fast from cache, and writes keep cache fresh without manual cache clearing.
Knowing how to separate read and write caching responsibilities avoids cache inconsistencies and improves app performance.
5
AdvancedCustomizing cache keys with @CachePut
🤔Before reading on: Do you think @CachePut uses method parameters or return values to generate cache keys by default? Commit to your answer.
Concept: @CachePut allows custom cache key expressions using SpEL (Spring Expression Language) for precise cache control.
By default, @CachePut uses method parameters to generate cache keys. You can customize keys using the 'key' attribute with SpEL. For example: @CachePut(value = "users", key = "#user.email") public User updateUser(User user) { ... } This caches the user by email instead of ID. You can also combine parameters or use complex expressions.
Result
Cache keys match your application's logic, preventing collisions and improving cache hit rates.
Understanding key customization prevents subtle bugs where cache entries overwrite each other or are missed.
6
AdvancedHandling cache update failures gracefully
🤔Before reading on: If cache update fails in @CachePut, does the method execution fail or succeed? Commit to your answer.
Concept: By default, cache update failures do not stop method execution, but you can customize error handling.
Spring's cache abstraction catches cache exceptions so the method still returns normally even if cache update fails. You can configure cache error handlers to log or handle failures differently. This prevents cache issues from breaking your business logic.
Result
Your application remains stable even if the cache system has problems.
Knowing this behavior helps design resilient systems that separate cache reliability from core logic.
7
ExpertInternal proxy mechanism of @CachePut in Spring AOP
🤔Before reading on: Does @CachePut modify the original method code or use proxies to add caching behavior? Commit to your answer.
Concept: @CachePut works by Spring creating a proxy around the method that intercepts calls to update the cache after method execution.
Spring uses Aspect-Oriented Programming (AOP) proxies to add caching behavior. When a method annotated with @CachePut is called, the proxy runs the method, captures the result, and then updates the cache. The original method code remains unchanged. This proxy mechanism allows caching to be added declaratively without modifying business logic.
Result
Caching is transparent to your code but powerful and flexible under the hood.
Understanding the proxy-based implementation explains why self-invocation inside the same class bypasses caching and how to avoid this common pitfall.
Under the Hood
@CachePut uses Spring's AOP proxies to intercept method calls. When the method runs, the proxy captures the return value and updates the cache with the specified key and cache name. The cache update happens after the method completes successfully. This mechanism separates caching logic from business code, making caching declarative and reusable.
Why designed this way?
Spring chose proxy-based AOP to add cross-cutting concerns like caching without changing existing code. This design allows developers to add caching declaratively via annotations, keeping business logic clean. Alternatives like bytecode manipulation were more complex and less transparent. The proxy approach balances flexibility, simplicity, and maintainability.
┌───────────────┐
│ Client Calls  │
└──────┬────────┘
       │
┌──────▼───────┐
│ Spring Proxy │
│ (@CachePut)  │
└──────┬───────┘
       │
┌──────▼───────┐
│ Original     │
│ Method Runs  │
└──────┬───────┘
       │
┌──────▼───────┐
│ Cache Updated│
│ with Result  │
└──────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Does @CachePut skip method execution if cache has data? Commit yes or no.
Common Belief:@CachePut behaves like @Cacheable and skips method execution if cache entry exists.
Tap to reveal reality
Reality:@CachePut always executes the method and updates the cache regardless of existing cache entries.
Why it matters:Believing this causes bugs where updates are not applied because the method never runs, leading to stale cache and data inconsistency.
Quick: Can @CachePut be used on methods that only read data? Commit yes or no.
Common Belief:@CachePut is suitable for any method, including read-only methods.
Tap to reveal reality
Reality:@CachePut is intended for methods that modify data and need to update the cache; using it on read-only methods causes unnecessary cache updates and performance loss.
Why it matters:Misusing @CachePut on read methods wastes resources and can degrade application performance.
Quick: Does @CachePut update the cache before or after method execution? Commit your answer.
Common Belief:@CachePut updates the cache before the method runs to prepare for the result.
Tap to reveal reality
Reality:@CachePut updates the cache only after the method successfully returns its result.
Why it matters:Assuming cache updates happen before method execution can lead to incorrect assumptions about cache state during method logic.
Quick: If a method annotated with @CachePut calls another method with @CachePut in the same class, will caching happen? Commit yes or no.
Common Belief:Self-invocation triggers caching annotations as usual.
Tap to reveal reality
Reality:Self-invocation bypasses Spring proxies, so caching annotations like @CachePut are ignored in internal calls.
Why it matters:This causes unexpected cache misses or stale data when methods call each other internally, confusing developers.
Expert Zone
1
The order of multiple caching annotations (@CachePut, @CacheEvict) on the same method affects cache state and must be carefully managed.
2
Using @CachePut with asynchronous methods requires attention because cache updates happen after method completion, which may be delayed.
3
Cache key generation can be customized with SpEL to handle complex scenarios like composite keys or conditional caching.
When NOT to use
@CachePut is not suitable when you want to skip method execution if cached data exists; use @Cacheable instead. Also avoid @CachePut on read-only methods to prevent unnecessary cache updates. For cache eviction scenarios, use @CacheEvict. For complex cache refresh strategies, consider manual cache management or external cache tools.
Production Patterns
In production, @CachePut is commonly used in service methods that update database records to keep caches synchronized. It is combined with @Cacheable on read methods for efficient caching. Developers often customize cache keys for multi-tenant or user-specific data. Error handling strategies ensure cache failures do not impact business logic. Monitoring cache hit rates and eviction policies helps maintain performance.
Connections
Aspect-Oriented Programming (AOP)
Builds-on
Understanding AOP explains how @CachePut adds caching behavior transparently without changing business code.
Database Transaction Management
Complementary
Knowing transaction boundaries helps ensure cache updates with @CachePut happen only after successful data commits, preventing cache inconsistency.
Memory Management in Operating Systems
Analogous
Just like OS manages memory cache to speed up access while keeping data fresh, @CachePut manages application cache to balance speed and data accuracy.
Common Pitfalls
#1Cache not updating after data changes
Wrong approach:@Cacheable(value = "users", key = "#user.id") public User updateUser(User user) { // update logic return user; }
Correct approach:@CachePut(value = "users", key = "#user.id") public User updateUser(User user) { // update logic return user; }
Root cause:Using @Cacheable on update methods causes cache to return stale data without running the update logic.
#2Cache update ignored on internal method calls
Wrong approach:public void updateAllUsers(List users) { for (User u : users) { updateUser(u); // updateUser has @CachePut } }
Correct approach:Use self-injection or call updateUser via Spring proxy: @Autowired private UserService self; public void updateAllUsers(List users) { for (User u : users) { self.updateUser(u); } }
Root cause:Self-invocation bypasses Spring proxies, so caching annotations are not applied.
#3Incorrect cache key causing collisions
Wrong approach:@CachePut(value = "users", key = "#user") public User updateUser(User user) { ... }
Correct approach:@CachePut(value = "users", key = "#user.id") public User updateUser(User user) { ... }
Root cause:Using the whole object as key can cause cache misses or collisions if equals/hashCode are not properly defined.
Key Takeaways
@CachePut always runs the method and updates the cache with its result, ensuring fresh data after updates.
It differs from @Cacheable, which may skip method execution if cached data exists.
Use @CachePut on methods that modify data and want to refresh cache entries immediately.
Spring uses proxies to implement @CachePut, so internal method calls bypass caching unless proxied.
Custom cache keys and error handling improve cache accuracy and application resilience.

Practice

(1/5)
1. What is the primary purpose of the @CachePut annotation in Spring Boot?
easy
A. To update the cache with the method's return value after execution
B. To clear all entries in the cache before method execution
C. To cache the method result only if it is not already cached
D. To disable caching for the annotated method

Solution

  1. Step 1: Understand the role of @CachePut

    @CachePut is used to update the cache with fresh data after the method runs, unlike @Cacheable which caches only if data is absent.
  2. Step 2: Compare options with @CachePut behavior

    Only To update the cache with the method's return value after execution correctly describes updating the cache after method execution. Others describe different caching behaviors.
  3. Final Answer:

    To update the cache with the method's return value after execution -> Option A
  4. Quick Check:

    @CachePut updates cache after method runs [OK]
Hint: Remember: @CachePut always updates cache after method runs [OK]
Common Mistakes:
  • Confusing @CachePut with @Cacheable
  • Thinking @CachePut clears cache
  • Assuming it caches only if absent
2. Which of the following is the correct syntax to use @CachePut to update a cache named "users" with a key based on the method parameter id?
easy
A. @CachePut(cacheName = "users", key = "id")
B. @CachePut(value = "users", key = "#id")
C. @CachePut(name = "users", key = "id")
D. @CachePut(cache = "users", key = "#id")

Solution

  1. Step 1: Recall correct attribute names for @CachePut

    The correct attribute for cache name is 'value' or 'cacheNames', and SpEL expressions for keys use '#'.
  2. Step 2: Analyze each option's syntax

    @CachePut(value = "users", key = "#id") uses 'value' and '#id' correctly. Others use incorrect attribute names or miss the '#' for SpEL.
  3. Final Answer:

    @CachePut(value = "users", key = "#id") -> Option B
  4. Quick Check:

    Use 'value' and '#param' for key in @CachePut [OK]
Hint: Use 'value' for cache name and '#' before param in key [OK]
Common Mistakes:
  • Using wrong attribute names like cacheName or cache
  • Missing '#' in key expression
  • Using plain string instead of SpEL for key
3. Given the following method in a Spring Boot service:
@CachePut(value = "products", key = "#product.id")
public Product updateProduct(Product product) {
    product.setPrice(product.getPrice() + 10);
    return product;
}
What will be the effect on the cache when this method is called with a product having id=5 and price=100?
medium
A. The cache is not affected because @CachePut only caches if absent
B. The cache entry with key 5 is removed from the cache
C. The cache entry with key 5 is updated with the product having price 110
D. A new cache entry with key 110 is added

Solution

  1. Step 1: Understand @CachePut behavior on method call

    @CachePut updates the cache entry with the key specified after the method returns the updated object.
  2. Step 2: Analyze the method logic and cache key

    The method increases price by 10 and returns the product. The key is product.id which is 5, so cache key 5 is updated with product price 110.
  3. Final Answer:

    The cache entry with key 5 is updated with the product having price 110 -> Option C
  4. Quick Check:

    @CachePut updates cache key with returned value [OK]
Hint: Returned value updates cache at key specified [OK]
Common Mistakes:
  • Thinking cache key changes to price
  • Assuming cache entry is removed
  • Confusing @CachePut with @Cacheable
4. Consider this method annotated with @CachePut:
@CachePut(value = "orders", key = "#order.id")
public Order updateOrder(Order order) {
    // missing return statement
}
What is the problem with this code?
medium
A. The method should be annotated with @Cacheable instead
B. The key expression is invalid and causes a syntax error
C. The cache name 'orders' is not allowed in @CachePut
D. The method does not return a value, so cache cannot be updated

Solution

  1. Step 1: Check method return requirement for @CachePut

    @CachePut requires the method to return a value to update the cache with that value.
  2. Step 2: Identify missing return statement issue

    The method lacks a return statement, so no value is returned to update the cache, causing runtime issues.
  3. Final Answer:

    The method does not return a value, so cache cannot be updated -> Option D
  4. Quick Check:

    @CachePut needs method return to update cache [OK]
Hint: Always return updated value when using @CachePut [OK]
Common Mistakes:
  • Forgetting to return the updated object
  • Confusing cache name attribute
  • Using @Cacheable instead of @CachePut incorrectly
5. You have a method that updates a user's email and you want to ensure the cache entry for that user is updated immediately after the change. Which approach correctly uses @CachePut to achieve this, assuming the method signature is public User updateEmail(Long userId, String newEmail)?
hard
A. @CachePut(value = "users", key = "#userId") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; }
B. @CachePut(value = "users", key = "#newEmail") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; }
C. @CachePut(value = "users") public void updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); }
D. @CachePut(key = "#userId") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; }

Solution

  1. Step 1: Verify correct cache name and key usage

    @CachePut(value = "users", key = "#userId") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; } uses 'value = "users"' and key '#userId', correctly identifying the cache and key.
  2. Step 2: Check method return and update logic

    @CachePut(value = "users", key = "#userId") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; } returns the updated User object, which is necessary for @CachePut to update the cache. Other options either use wrong key, no return, or missing cache name.
  3. Final Answer:

    @CachePut(value = "users", key = "#userId") public User updateEmail(Long userId, String newEmail) { User user = userRepository.findById(userId); user.setEmail(newEmail); userRepository.save(user); return user; } -> Option A
  4. Quick Check:

    Return updated object and use correct cache name and key [OK]
Hint: Return updated object and use correct cache name and key [OK]
Common Mistakes:
  • Using wrong key expression
  • Not returning updated object
  • Omitting cache name in annotation
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard