1 of 1 people found this helpful
We've recently run into some performance bottle neckes when fetching small amounts data lots of times using Hibernate, basically the opening and closing of Hibernate sessions is becoming a big overhead (data is in second level cache) and we want to put a cache infront of Hibernate.
are you sure that just opening and closing of Hibernate sessions is the overhead you detected? Opening a new session is very efficient, what could be slow is the dirty checking at flush time, but you can avoid it by loading entities in detached mode or read-only.
Detached or read-only entities are not very useful as obviously you can't use them to apply changes to the database, but that seems to be your plan anyway as if you load them via a CacheLoader you would have the same limitation.
To do this I would like to implement a custom CacheLoader which delegates to a our own data access code (JPA, JDBC, etc.) for loading a single entry or loading all. In my case a cache deals with one entity.
Had a quick look at the CacheLoader interface and doesn't look as straight forward to do as I first imagined and thought I'd ask here if there are any examples available to have a look at?
Sure, it's open source, you could checkout the project and have a look at any of the implementations. I guess you're aware already of the modules infinispan-cachestore-remote, infinispan-cachestore-jdbc, infinispan-cachestore-jdbm, infinispan-cachestore-... ?
They are all feature-complete, but a simpler start could be to look into
which can be found in the testsuite of infinispan-core.
If this is useful for you I couldn't say, it looks like you have a very special use case: the CacheLoader you'll implement will return detached and unrelated instances, each one loaded from a different transaction, so you're going to loose a lot of the benefits of Hibernate.
Personally I have the idea that using the second level cache would be much better as it will be able to load the same values but in a known transactional scope and resolving relations too, but please let me know about your use case.
Remember that if you implement this you also will need to update the cache when updating the values via Hibernate, you could do that using an Hibernate event listener.
Finally, make sure that different cache clients make defensive copies of the entities they load before modifying them as the same instance might have been returned to another thread; when using the second level cache returned instances are new, as the entities are not cached directy but it's the jdbc query result which makes them which is cached, so Hibernate isolates different clients.
Sorry for the delay in replying, been on holiday.
Many thanks for the detailed reply, really appreciate it! Below is a bit of an expleanation of what we do.
First off we only want a read-only cache, this is reference data we load which won't be updated.
It was definitely hibernate session creation which slowed down our process. Basically I switched from pre-loading a 20 odd values in to a map, to fetching them via JPA that is configured with a second level cache. I could see that each entity was only feteched once from the database and subsequently retrieved from the second level cache.
When "widening" the transaction, cutting the transactions created by half that reduced the time to process the data by half.
Basically our application is an extract transform and loading app which deals with a lot of data which processes millions of records (the data feed where I noticed the slowdown only processes on average 12K records though). So what is normally not a massive overhead, session creation, seems to create a noticable impact for us.
This is why I want to prototype putting the cache infront of hibernate, using a cache loader to get the data via hibernate when needed.
I'll have a look at the examples you suggested, was seceretly hoping that the CachLoader mechanism would be as simple as the one used by Coherenece (only has load and loadAll methods)