1

I want to use google Cache to cache my data,So I write the code like this.I find that it can only pass one parameter that called key,But In my method,I have the other parameter,How to fix my code?

 private LoadingCacheS<tring, List<Map<String, Long>> getCache(String key,Map<String,String> para1,
 String para2){
 retrun CacheBuilder.newBuilder()
            .refreshAfterWrite(20, TimeUnit.MINUTES)
            .expireAfterWrite(30, TimeUnit.MINUTES)
            .maximumSize(1)
            .build(new CacheLoader<String, List<Map<String, Long>>>() {
                @Override
                public List<Map<String, Long>> load(String key) throws Exception {
                    return queryData(key); //can not get the other para
                }

                @Override
                public ListenableFuture<List<Map<String, Long>>> reload(String key, List<Map<String, Long>> oldValue)
                        throws Exception {
                    ListenableFutureTask<List<Map<String, Long>>> task = ListenableFutureTask
                            .create(() -> queryData(key));
                    executorService.execute(task);
                    return task;
                }

In my queryData method,I have three parameters,How to change my code?

private List<Map<String, Long>> queryData(String key,Map<String,String> para1,
 String para2){
  //query data and return data
  }
flower
  • 2,212
  • 3
  • 29
  • 44

1 Answers1

2

In these types of cases you have multiple options.

If all of the parameters are part of the mapping, then you can use a composite key. A data class that holds all parameters and correctly implements equals and hashCode is the cache key.

Sometimes these parameters irrelevant to the key but the parameters are part of a lifecycle scoped, e.g. to the http request such as the user's access token. In those cases you may be using a dependency injector like Guice that is aware of this lifecycle. In those cases you can inject a Provider<T> (or equivalent) instead and resolve the parameter at runtime.

The last option is to not use a CacheLoader but instead use cache.get(key, loader). The loader, a Callable, is a "capturing lambda" which means that it has access to parameters in the surrounding scope. The drawback of this approach is that you cannot use refreshAfterWrite since that requires a CacheLoader.

Ben Manes
  • 9,178
  • 3
  • 35
  • 39
  • The cache key is only one string like id; but the result is query by id and other paramete.r – flower Jan 17 '21 at 05:33
  • In those cases you can inject a Provider (or equivalent) instead and resolve the parameter at runtime..Can you give a example,please? I can not get your ideal. – flower Jan 17 '21 at 05:36
  • @flower Do those parameters affect the results, as in would two calls by the same `id` ever use different parameters such that they would retrieve different data? If so, then you likely want to use a composite key. – Ben Manes Jan 17 '21 at 05:37
  • 1
    @flower See the [Guice documentation](https://github.com/google/guice/wiki/InjectingProviders#providers-for-mixing-scopes) for an example. This is like a `Supplier` that can query for `T` lazily at runtime, since that value may change. For example if the http request binds a `Provider` to `John Doe` then the call on that request gets that user, whereas the next call may obtain the user `Jane Doe`. The `CacheLoader` gets a strategy to obtain the parameter, rather than the parameter directly. – Ben Manes Jan 17 '21 at 05:40
  • Now I put the other two parameters in to the global variable. For example, the key id is to get all the data like select * from table. But the other parater may fileter the data, like select columnA,columnB from table where name='C'; – flower Jan 17 '21 at 05:46
  • @flower If you for the same key id you select different columns, then the cache might load columnA and while the request asks for columnB. In that case your cache key should be (id, columns). If you will always obtain the same set of columns, then obtaining those columns elsewhere (like the global) makes sense. – Ben Manes Jan 17 '21 at 05:50
  • 1
    ,the key and the paramter is one to one relation. – flower Jan 17 '21 at 05:54