Reputation: 3753
I am using spring cache abstraction to cache objects in the service layer. This is fine for simple get/put operations, as follows:
static private final String cacheName = "messages";
@CacheEvict(value=cacheName, key="#message.id")
public void deleteMessage(Message message) {
...
}
@Cacheable(value=cacheName, key="#id")
public Message findMessage(Long id) {
...
}
@CachePut(value=cacheName, key="#message.id")
public void saveMessage(Message message) {
...
}
@CachePut(value=cacheName, key="#message.id")
public Message updateMessage(Message message) {
...
}
However, what annotation would I use for the following method:
public long countAllMessages() {
...
}
Since all the objects will be in the cache, there should be a way to get the answer from the cache and not having to go to the repository layer.
Also, the cache is being applied on the following method:
@Cacheable(cacheName)
public List<Message> findAllMessages() {
...
}
I could make the count method call the find all method like this:
public long countAllMessages() {
return findAllMessages().size();
}
But this would not be efficient in the case where the cache is disabled, as the call would then load all records from the db instead of doing a SELECT COUNT(*)...
Upvotes: 11
Views: 18145
Reputation: 604
The Spring cache abstraction doesn't currently provide a direct way of accessing statistics about the underlying caches. For example, there is no direct way to get the size of all the caches, the keys of the cached objects, etc. It's a higher level abstraction than that. You can, however, get access to the underlying native cache classes via the Cache#getNativeCache() method. Grabbing an instance of Cache from the CacheManager class will give you access to this method. Assuming you know the underlying types of the Cache instances managed by the CacheManager, you can cast them to the appropriate types and gain access to the helper methods on each (assuming there are any).
For example, if your underlying cache store is EHCache, you can grab an instance of the Cache named "messages" by calling CacheManager#getCache("messages"). You'd then be able to check the type and cast the type to net.sf.ehcache.Ehcache, from which you can call the various statistics helper methods (eg. getStatistics()).
Here's an example of going through all the caches managed by CacheManager, checking if they're of type net.sf.ehcache.Ehcache, and subsequently getting their statistics.
public class EhCacheStatistics {
private CacheManager cacheManager;
@Inject
public void setCacheManager(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
public long getTotalEhCacheSize() {
long totalSize = 0l;
for (String cacheName : cacheManager.getCacheNames()) {
Cache cache = cacheManager.getCache(cacheName);
Object nativeCache = cache.getNativeCache();
if (nativeCache instanceof net.sf.ehcache.Ehcache) {
net.sf.ehcache.Ehcache ehCache = (net.sf.ehcache.Ehcache) nativeCache;
totalSize += ehCache.getStatistics().getObjectCount();
}
}
return totalSize;
}
}
Upvotes: 19