Does anybody know how the default key generation for Ehcache works? If I have the following method:
@Cacheable(cacheName = CACHE_KEY) // CACHE_KEY is static final field.
public List<DataObject> list(
int firstRecord, int maxRecords, int pageSize, FilterObject filter) {
....
}
where FilterObject
is a custom POJO, what should I expect to be the actual cache key?
What I am observing is when using different FilterObject
instances and not changing the other arguments of my method call, it always produces the same result - the first call's result is cached and returned.
Probably it is the FilterObject
POJO which causes the behaviour - I suppose it is either some serialization, or .toString()
issue, because I haven't overridden the relevant methods.
Still I was unable to find exact information on how the cache key for such method is being formed both in Ehcache's website and in the @Cacheable
annotation documentation.
I'd appreciate any information and recommendations on this topic.
You can think Redis as a shared data structure, while Ehcache is a memory block storing serialized data objects. This is the main difference. Redis as a shared data structure means you can put some predefined data structure (such as String, List, Set etc) in one language and retrieve it in another language.
EhCache is a widely used, pure Java cache that can be easily integrated with most popular Java frameworks, such as Spring and Hibernate. It is often considered to be the most convenient choice for Java applications since it can be integrated into projects easily.
@CacheableThis method-level annotation lets Spring Boot know that the return value of the annotated method can be cached. Each time a method marked with this @Cacheable is called, the caching behavior will be applied.
EhCaching Storage Tiers are as follows: On-Heap Store: Java heap memory is used to store cache entries. Off-Heap Store: It stores cache entries into primary memory (RAM). Disk Store: It uses a disk to store cache entries. Clustered Store: Remote server is used to store cache entries.
This is the default key generator
public class DefaultKeyGenerator implements KeyGenerator {
public static final int NO_PARAM_KEY = 0;
public static final int NULL_PARAM_KEY = 53;
public Object generate(Object target, Method method, Object... params) {
if (params.length == 1) {
return (params[0] == null ? NULL_PARAM_KEY : params[0]);
}
if (params.length == 0) {
return NO_PARAM_KEY;
}
int hashCode = 17;
for (Object object : params) {
hashCode = 31 * hashCode + (object == null ? NULL_PARAM_KEY : object.hashCode());
}
return Integer.valueOf(hashCode);
}
}
As you can see, it combines the hash-codes of each method parameter.
Everything is explained in Spring reference documentation, namely in:
[...]
- If more the one param is given, return a key computed from the hashes of all parameters.
To provide a different default key generator, one needs to implement the
org.springframework.cache.KeyGenerator
interface. Once configured, the generator will be used for each declaration that doesn not specify its own key generation strategy (see below).
and below:
[...] the @Cacheable annotation allows the user to specify how the key is generated through its key attribute. The developer can use SpEL to pick the arguments of interest[...]
And an example from the docs:
@Cacheable(value="books", key="#isbn.rawNumber")
public Book findBook(ISBN isbn, boolean checkWarehouse, boolean includeUsed)
So in your case you should simply implement equals()
and hashCode()
for FilterObject
. Decent IDE can generate them for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With