@Caching With Multiple Keys
Solution 1
Yes, you can specify using a Spring-EL expression along these lines:
@Override
@Cacheable(key="#bar.name.concat('-').concat(#bar.id)")
public int foo(Bar bar) {
....
}
or define a modified hashCode on bar and call that:
@Override
@Cacheable(key="#bar.hashCodeWithIdName")
public int foo(Bar bar) {
....
}
Solution 2
You can use this approach also
@Override
@Cacheable(key="{#bar.name, #bar.id}")
public int foo(Bar bar) {
....
}
It is suggested not to use hashcode as keys @Cacheable key on multiple method arguments
Solution 3
You can use Spring SimpleKey class
@Cacheable(value = "barCache", key = "new org.springframework.cache.interceptor.SimpleKey(#bar.id, #bar.name)")
Solution 4
Both answers by @Biju and @vsingh are correct; but I would like to add one more alternative if the Bar
object you are trying to cache is complex or the foo
method contains a large amount of parameters using SpEL might not be the most ideal solution for generating the key.
Alternatively you may want to consider keyGenerator
.
Example:
@Override
@Cacheable(value="barCahceKey", keyGenerator="barKeyGenerator")
public int foo(Bar bar) {
....
}
@Component
public class BarKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object o, Method method, Object... objects) {
// TODO logic to generate unique key
return "Bar_Key_Generator_With_Params_etc";
}
}
With this approach you have the fully flexibility of how the key is constructed.
Alex Beardsley
Updated on July 31, 2022Comments
-
Alex Beardsley almost 2 years
I have a service that takes in a DTO and returns some result:
@Override public int foo(Bar bar) { .... }
Bar is as follows (simplified):
public class Bar { public int id; public String name; public String baz; @Override public int hashCode() { //this is already being defined for something else ... } @Override public boolean equals(Object o) { //this is already being defined for something else ... } }
I want to use @Cacheable on the foo method; however, I want to hash on the id and name properties, but not baz. Is there a way to do this?
-
Balázs Németh over 3 yearsDoes this answer your question? @Cacheable key on multiple method arguments
-
-
NBJack about 3 yearsHash codes are dangerous as they aren't guaranteed to be unique.
-
Sanjay almost 3 yearsBut when I use this approach it's throwing
java.lang.ClassCastException: Invalid key type, expected : org.springframework.cache.interceptor.SimpleKey but was : java.util.ArrayList
. How can I get over this? -
Sanjay almost 3 yearsThis works for but why does @vsingh solution gives me
java.lang.ClassCastException: Invalid key type, expected : org.springframework.cache.interceptor.SimpleKey but was : java.util.ArrayList
exception? -
Sanjay almost 3 yearsBut why does it require
key = "new org.springframework.cache.interceptor.SimpleKey(#bar.id, #bar.name)"
instead ofkey = "{#bar.id, #bar.name}"
-
study_20160808 almost 3 yearsIf '-' is public static final String data. How should I do?
-
Akanksha gore over 2 yearsCustom keyGenerator allow to create only 1 key. What about having multipe keys from KeyGenerator? This KeyGenerator only return Object not array of object. So, I guess custom KeyGenerator cannot be used for multiple key generation.