2

I am interested in using Spring's Cache Abstraction on a module that I am working with but all data operations are on collections to avoid multiple datasource invocations, so I am not sure I have a decent "pointcut" at which to method-level cache. This is not a Spring or Java specific issue but more of a design problem.

For example:

public class SomeDataAccessObject{
 private SomeBatchingDataSourceAbstraction datasource;

 //would ideally add a cache annotation to this method to cache based on input, but that   
 //clearly won't work in this scenario because we are loading multiple which may have 
 //some cache hits only
 public List<String> getNames(List<Integer> ids){
  //ideally I would load as many names as I can from the cache and 
  //then use the datasource to get the rest
  //I can achieve this with a programatic cache but it is very invasive
  return datasource.fetch(ids);
 }

}

Has anyone come up with a good way to redesign such a scenario that would allow me to use Spring-style method level declarative caching? Please remember that I want to keep the data access object (above) effectively stateless in order to be thread safe.

  • Is there such a thing as a "stateless" cache? Isn't cache really just a bag of "forwarded state?" Do you ever intend to invalidate the cache and refresh its contents? Have you considered other solutions like Lazy Loading? – Robert Harvey Jan 23 '15 at 16:58
  • @RobertHarvey The cache would not be stateless. I just want the example object to remain stateless so that I can use it as a Singleton in the app (ex/ no temporary class level attributes that represent the current data being loaded). The cache is lazy...it will only be populated when get is called (method level caching). I would leave the eviction policies to the implementation I end up choosing...this is only referring to the abstraction. – smp7d Jan 23 '15 at 17:02
  • 1
    @RobertHarvey it is rather easy to convert the LinkedHashMap into an LRU cache by subclassing it and overriding the removeEldestEntry method. – user40980 Jan 23 '15 at 17:03
2

I don't believe this can be accomplished via Spring's cache abstraction, its design doesn't appear to support your use case (unless I'm misunderstanding your intent).

Spring's method level caching hinges on the ability to generate a unique key given the method parameters via a KeyGenerator. This simple key-value store approach will not work since you expect a subset of the data to be cached depending on the specific IDs being passed in.

If you're looking to cache based on the subset of IDs in the invocation, utilizing the JPA/Hibernate query cache may meet your needs.

Spring 4 by default uses the new SimpleKeyGenerator, which produces SimpleKey objects utilizing hashCode() and equals() contracts - delegating to Arrays.deepHashCode() and Arrays.deepEquals() for method invocations with multiple parameters.

  • Yes, I was kind of hoping there were an existing extension to Spring (or a trick) that would provide support for this or that there was a design pattern that I could utilize behind this method that would assist me. – smp7d Jan 29 '15 at 2:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.