简体   繁体   中英

Cache a whole database using Spring, Hibernate, and Ehcache

I am working on an application which relies on caching using mostly reads and some updates.

The technology stack I am using is Spring + Hibernate + Ehcache. I need to serve the requests using the cache and not hit the database at all. The approach I am following is to cache all of the data at the application start up using queries such as getSession().createCriteria(<Entity>.class).list() and then ask Hibernate for entities using a session.get() call so that it uses the second level cache to resolve.

One challenge I see is my entity classes have a lot of collection and association attributes (Many-to-Many with extra columns, One-to-Many, One-to-One).

I have two approaches for such a cache:

  1. Keep all relationships as EAGER fetch. The cache will be filled with the data with a big query containing left outer joins on startup. I am concerned that loading data eagerly may cause unnecessary long running queries returning multiple rows.

  2. Keep relationships as LAZY and iterate over all the rows and call .getSetOf<Entity> to load related entities. I am concerned that I will be virtually iterating all of the data at startup and I'm not sure if whether this is a good practice.

Since the associations in Hibernate are associated using composition and foreign keys and not stored as individual IDs, loading of such associations/collections seems to be overhead.

I would have preferred having table data in different cache regions with their foreign key relationships as just IDs (not compositions/collections). I would have cached all such entities in different regions and would have combined the results at runtime by iterating over those regions.

Can anyone suggest what approach should I follow? If there is any alternate approach, do suggest.

I am working on a project having technology stack spring+hibernate+hazelcast . I am using hibernate 2nd level cache also. We also load data into cache on server startup. According to me you should not do all collections of an entity eager as it makes the object very heavy.We are using mixed approach.Some of our collections are eager and some are lazy depending upon the requirement. If your collection has very large data then make it lazy otherwise make it eager. One more thing we are doing,we are using LEFT JOIN FETCH in queries which loads the collections also if collections are defined lazy.For eg:-

SELECT DISTINCT userInfo FROM UserInfo userInfo
LEFT JOIN FETCH userInfo.userRoles
LEFT JOIN FETCH userInfo.regions
LEFT JOIN FETCH userInfo.countries

In my entity UserInfo , i have made region Eager (because regions are less in number) and countries Lazy (because countries are more in number).Now my this query still returns userInfo object fully loaded with countries and region.And due to Left Join Fetch no multiple queries get executed.

I hope this can help you.

It's not clear from your description if your application controls access to the database.

  • If not then the performance documentation states you risk having stale data. What do you do in this case?
  • If it is and only if you really need to minimize the number of db hits then I wouldn't use Hibernate nor Ehcache. Not much ORM going on except for the initial load which in my opinion doesn't make it much of a usecase for Hibernate. I'd use Spring JDBC with a batch select on startup. This will reduce the number of calls and a possible out of memory exception (a "normal" select statement references its read data, so as you progress throug the records you'll have more references which cannot be GC'ed). It also reduces your technology stack with 1 burden less. You can update the cache and database as soon as you change state. You may need to take into account the transaction scope. Left joins can be tackled within your mapper. I'd also drop the OO approach and use arrays or maps of data. Encapsulating each group of data with an object just for the sake of it may be overkill (memory consumption, cpu, ...). Especially the load-it-all-once requirement makes me think not a lot of interaction is happening here. And drop Ehcache. If you really need to minimize you database calls you can as well put everything in a Map as no eviction strategy is necessary.

Just to make it clear, I'm not anti OO or Hibernate or Ehcache. I'm just wondering if they're a good fit for your (limited) description.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM