Caching Data with Spring
What is Cache?
The Cache frequently uses data storage that can be accessed at high speed. If any requests to data is configured to enable caching, data can be accessed faster than it would be by accessing the original storage because caching data is purposely stored in a space for quick access. Data that is sought or calculated before is able to be reused efficiently by caching.
The Spring Framework provides support for adding cache with minimal impact on code. The reason why this is possible is that the Spring Framework provides the caching abstraction, not caching implementation.
The caching abstraction in Spring Framework can add to the method transparently using AOP’s structural feature when running the method. Because of AOP, the Cache in Spring Framework can be applied to various implementations of that abstraction; for example, JDK java.util.concurrent.ConcurrentMap
based caches, Ehcache 2.xx
, Gemfire Cache
, Caffeine
, and JSR-107
compliant caches.
In other words, we can add or modify caching easily to the method without applying cache API and codes. When the application environment or type of applied cache changes(e.g. application version, deprecated methods), the application code is not impacted significantly due to the caching abstraction.
To use caching in Spring Framework, you have to configure the CacheManager
first. Let’s see what kind of CacheManager
there is.
📌 Cache Manager
The caching abstraction should register the CacheManager
supported to enable caching to the Bean.
✔️ SimpleCacheManager
Simple CacheManager
working against a given collection of caches. This can be useful for testing or simple caching declarations.
@Bean
public CacheManager cacheManager() {
Cache cache = new ConcurrentMapCache("byUsername");
SimpleCacheManager manager = new SimpleCacheManager();
manager.setCaches(Arrays.asList(cache)); return manager;
}
✔️ ConcurrentMapCacheManager
The ConcurrentMapCacheManager
is using ConcurrentHashMap
in the default java package. There is an advantage of not needing an additional configuration because of saving cache data to the default Map
type in memory, but it is poor for a real service. This is because dealing with cache requires a lot of skills but the ConcurrentHashMap
is a structure in which complex caching cannot be used.
In my opinion, I recommend using this CacheManager
for the demo or test application because it uses default Java packages which do not require configuration.
✔️ EhCacheCacheManager
The CacheManager
is supported by the EhCache
which is one of the popular cache frameworks in Java.
✔️ CaffeineCacheManager
The CacheManager
is supported by the CaffeineCache
which is rewritten GuavaCache
for performance in Java 8. Caffeine
is a rising one of the caching services because of its faster performance than EhCache.
✔️ CompositeCacheManager
This is for composite CacheManager one or more.
📌 @EnableCaching
To add caching to the methods, you have to declare @EnableCaching
in Spring Framework.
You can apply it easily by annotating the configuration Class like the codes below.
✔ Code
@EnableCaching
@Configuration
public class EhCacheConfiguration { /* ... */}
📌 @Cacheable
If @Cacheable
annotation is set up on the method, the set method return value is stored.
If the method calculates data previously, the caching value exists in storage and the method is not necessary to calculate at each request because the stored data is returned instead.
The caching is saved on the base of cacheName. If it should be indicated in detailed individual values, it can be set up as the key name like the following example.
@Cacheable(cacheNames = "platformBooks")
public Book getPlatformTeamBook(int bookId) { /* ... */}// or@Cacheable(cacheNames = "platformBooks", key = "#root.target + #root.methodName + '_'+ #p0")
public Book getPlatformTeamBook(int bookId) { /* ... */}
@CacheEvict
The @CacheEvict
annotation removes the stored caching data when the method is called. This is necessary for changing calculated data because there is a gap between existing stored caching data and calculating data.
@CacheEvict(value = "platformTeamBooks", allEntries = true)
public Book insertPlatformTeamBook(BookVO bookVO) { /* ... */}
@CachePut
The @CachePut
annotation use uses only storing cache.
Similar to @Cacheable
annotation, @CachePut
stores in the cache memory but its annotation does not use caching data, instead, it just only gets a purpose of storing. Instead, it only works for storage purposes.
@Cacheable(key = "testKey", condition="#caching")
public Object modifySome(boolean caching) {/* ... */}