views:

484

answers:

3

I use JBoss AS. I have a long and heavy SQL that run inside the application server. I want to cache the results based on input parameters.

I have a few options here:

  1. Use a caching manager and manually putting the results in the cache.

  2. Use a caching manager with loader that will "load" the results into cache when there's no results in cache.

I don't care for now about replication of the cache to other servers in cluster.

My question is what option should I choose? What are the benefits and drawbacks of each option. (ease of deployment, configuration mess)

Is this can be implemented using JBoss Cache or ehcache or both.


Update: I am using hibernate but the results are not entities, they are counters. I need to count all rows that belong to specific category and have specific status. I want that result to be cached.

Should I wrap the results inside an entity? Then, how can I make it work like (materialized?) view in oracle - to be update automatically or by trigger.

+2  A: 

For starting a WeakHashMap can probably do what you need for now.

Create two classes, a Key holding the values needed to identify the key (remember to implement equals() and hashcode()), and a Value holding the retreived values as pulled out from the ResultSet. The easiest is probably a List of Maps (a map per row).

Java will automatically invalidate the entries when running out of memory in a WeakHashMap.

Thorbjørn Ravn Andersen
+2  A: 

You're going to have to get the data out of the ResultSet and into objects in order to cache it so why don't you just start using Hibernate, which provides caching using a verity of options inclucing Ehcache, JBoss Cache and a simple Map.

http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance-cache.html

Nick Holt
While I agree with the above, converting an existing app to Hibernate can be a pain, and should not be considered a small task.
Jesse
I am using hibernate and the queries are for example count all rows with specific category, status, etc. I want to cache the counter.
Vitaly Polonetsky
With knowing more about the problem I'd be inclined to treat the counters as domain objects loading them via Hibernate. You've got 2 options on how to do that - either define custom SQL that provides a result set with the counts and status in or create a view the does the same thing. I'd be inclined to use a view but like I say without knowing the exact details it's hard to say. You'll also have to deal with cache synchronization but that problem will exist whatever solution you choose.
Nick Holt
Do you have an examplefor doing this with native SQL? Or using just custom HQL, almost like a view.
Vitaly Polonetsky
Take a look at http://docs.jboss.org/hibernate/stable/core/reference/en/html/querysql-load.html - should explain what you need to do.
Nick Holt
A: 

If you just want a quick roll-your own caching solution, have a look at this article on JavaSpecialist, which is a review of the book Java Concurrency in Practice by Brian Goetz.

It talks about implementing a basic thread safe cache using a FutureTask and a ConcurrentHashMap.

The way this is done ensures that only one concurrent thread triggers the long running computation (in your case, your SQL call). Without doing something like this, then you are in danger of multiple threads triggering your SQL call when your cache is empty, e.g. if you are under heavy load immediately after you've started your app server. Obviously, its up to you to judge if that is a problem for you, or if you'd be happy a simpler solution where the last thread to complete puts its result in the cache.

You'd have to modify this solution to add cache expiry if you need it. Also, it wouldn't release the memory, like Thorbjørn's suggestion of using a WeakHashMap.

A_M