java - How to use cache with queries on different fields/keys? -
i implementing spring mvc based web application have added caching, face problem in terms of how operate on cache when changes applied underlying database.
i have been studying documentation available @ ehcache (http://ehcache.org/documentation), failed find examples solve problem.
let's have dao class have chosen apply cache on 2 methods return list of objects (non-compileable pseudocode):
@repository public class myentitydao { @autowired datasource ds; @autowired ehcachecachemanager cachemanager; @autowired cachekeygenerator keygenerator; @cacheable("myentitycache") public list<myentity> findbyfieldalpha(string fieldalpha) { return ds.query("select * myentity fieldalpha = #fieldalpha").execute(); } @cacheable("myentitycache") public list<myentity> findbyfieldbeta(string fieldbeta) { return ds.query("select * myentity fieldbeta = #fieldbeta").execute(); } public void deletebyfieldalpha(string fieldalpha) { ds.query("delete myentity fieldalpha = #fieldalpha").execute(); } public void deletebyfieldbeta(string fieldbeta) { ds.query("delete myentity fieldbeta = #fieldbeta").execute(); } public void store(myentity myentity) { ds.insert(myentity).execute(); } }
i using custom keygenerator, know how keys when calling method generated:
public class cachekeygenerator implements keygenerator { @override public object generate(final object target, final method method, final object... params) { return generatecachekey(method.getname(), params); } public string generatecachekey(final string methodname, final object... params) { stringbuilder key = new stringbuilder(); key.append(methodname); (object o : params) { key.append("_").append(o.tostring()); } return key.tostring(); } }
the obvious problem need solve how should implement cache modification policy when data added or removed underlying database.
for store method find problem quite trivial solve:
... public void store(myentity myentity) { boolean success = ds.insert(myentity).execute(); if (success) { cache cache = cachemanager.getcache("myentitycache") string keyfieldalpha = keygenerator.generatecachekey("findbyfieldalpha", myentity.getfieldalpha()); list cachelistfieldalpha = (list) cache.get(keyfieldalpha).getobjectvalue(); cachelistfieldalpha.add(myentity); string keyfieldbeta = keygenerator.generatecachekey("findbyfieldbeta", myentity.getfieldbeta()); list cachelistfieldbeta = (list) cache.get(keyfieldbeta).getobjectvalue(); cachelistfieldbeta.add(myentity); } }
but delete-methods things more complicated.
this 1 implementation have come far, seems far more complicated (costly) should be. have valuable input if design patterns correct, or if should solve problem in other way?
public void deletebyfieldalpha(string fieldalpha) { list<myentity> myentititestobedeleted = this.findbyfieldalpha(fieldalpha); boolean success = ds.query("delete myentity fieldalpha = #fieldalpha").execute(); if (success) { cache cache = cachemanager.getcache("myentitycache") string keyfieldalpha = keygenerator.generatecachekey("findbyfieldalpha", fieldalpha); cache.remove(keyfieldalpha); (myentity myentity : myentititestobedeleted) { string keyfieldbeta = keygenerator.generatecachekey("findbyfieldbeta", myentity.getfieldbeta()); list cachelistfieldbeta = (list) cache.get(keyfieldbeta).getobjectvalue(); cachelistfieldbeta.remove(myentity); } } }
perhaps correct way of solving it? haven't stumbled upon recipes solves these problems @ best guess here.
i'll give opinion. seems (almost) correct aproach. think after delete operation should empty cache , start again. usualy, after data changing operations cache reset. that's done because of table joins. doesn't seem case because have 2 queries , no joins, usualy cache cleaned , restarted. doing way don't need scan on cache refers "fieldbeta" after changes in "fieldalfa". hope somethig you. btw, mybatis works way.
Comments
Post a Comment