It's impossible to do it for collections with the Spring's annotations - with @Cacheable you'd have just one element in a cache with a computed key and a value with the whole list inside.
If performance is not that important in your app, use getCustomer(...) in a loop.
Otherwise, you'll need to update your cache manually. Unfortunately, Cache interface doesn't provide a method to retrieve all keys/values/key-value pairs from a cache, so a bit of casting is required.
The example for the default in-memory cache (spring.cache.type=simple):
@Autowired
private org.springframework.CacheManager cacheManager;
public List<Customer> allCustomers() {
ConcurrentMap<Long, Customer> customerCache = (ConcurrentMap<Long, Customer>)
cacheManager.getCache("customer").getNativeCache();
if (!customerCache.isEmpty()) {
return new ArrayList<>(customerCache.values());
}
List<Customer> customers = db.values().stream().collect(Collectors.toList());
customers.forEach(customer -> customerCache.put(customer.getId(), customer));
return customers;
}
Or for spring.cache.type=jcache with backed EhCache 3:
@Autowired
private org.springframework.CacheManager cacheManager;
public List<Customer> allCustomers() {
javax.cache.Cache<Long, Customer> customerCache = (javax.cache.Cache<Long, Customer>)
cacheManager.getCache("customer").getNativeCache();
Iterator<Cache.Entry<Long, Customer>> iterator = customerCache.iterator();
List<Customer> cachedCustomers = new ArrayList<>();
while (iterator.hasNext()) {
Cache.Entry<Long, Customer> entry = iterator.next();
cachedCustomers.add(entry.getValue());
}
if (!cachedCustomers.isEmpty()) {
return cachedCustomers;
}
List<Customer> customers = db.values().stream().collect(Collectors.toList());
customers.forEach(customer -> customerCache.put(customer.getId(), customer));
return customers;
}
The same can be done similarly for any other cache type (redis, hazelcast, caffeine etc.).
The corresponding eviction method can be written much easier:
@CacheEvict(value = "customer", allEntries = true)
public void deleteAllCustomers(){
db.removeAll(); //pseudocode
}