1

I have clients that request from my application same data basically every 5 seconds. At the moment, I am querying the database for every user, but this does not appear to be an efficient solution.

I am considering creating a thread safe singleton described in this answer that will contain that one object and that object will refresh every few minutes.

Is this the right path, or do you have any other advice?

To me, this seems like a common problem, and I think that there probably is an out of the box solution.

Community
  • 1
  • 1
Ivan Pavić
  • 528
  • 4
  • 22
  • How are you hitting the database? – Evan Knowles Jul 09 '15 at 10:42
  • 1
    You can use a cache framework like EHCache, and set up cache expiry to 5 minutes. You lookup in cache for data, if found you return it. If not found, you query DB and add to cache – Wand Maker Jul 09 '15 at 10:45
  • @EvanKnowles I have fiew simple SQL queries and Adapter that maps responses in one object Problem is thread safety, data is not changed frequently ( every 30-45 minutes), but not static – Ivan Pavić Jul 09 '15 at 10:52
  • Perhaps consider going for a DB framework with built-in caching, like Hibernate. – Evan Knowles Jul 09 '15 at 11:14

3 Answers3

2

The design pattern you are referring to here is a cache.

If the data is relatively static, you can cache the database response in some way, perhaps in a Map with some sort of key built from the parameters of the request and perhaps with some expiration based on time (e.g. 1 hour or 1 day).

A Singleton is indeed an implementation of a sharable object, such as the cache that you need. Note that the other answer that you refer to talks about thread safety. This can be especially important in (for example) a web service environment where threads can be used per-session or per-request.

Note that Singletons are regarded by many as being bad programming practise, not least since they are hard to test.

So another way to implement the cache would be via a singleton thread-safe cache bean, and "wire" it in to all places that it needs to be used via dependency injection.

PS. Guava libraries have a cache builder that can be configured withe time-based expiration poilicies.

PPS. if you want to cache across multiple servers you could consider a grid solution like hazelcast.

vikingsteve
  • 38,481
  • 23
  • 112
  • 156
  • If i went with singleton thread safety would be an issue, because threads are created "per request", thx for cashe pattern hint – Ivan Pavić Jul 09 '15 at 10:56
1

If your data is read often but doesn't change frequently (or is even static) then cqengine is your friend

usr-local-ΕΨΗΕΛΩΝ
  • 26,101
  • 30
  • 154
  • 305
1

If you don't mind some of your "users" taking the hit for going to the DB, you can get away with simple caching as in the following:

    import java.util.concurrent.atomic.AtomicLong;

    public class DbData {

         AtomicLong lastVisistToDB = new AtomicLong();
        volatile Object dataFromDb;
        long freshnessInterval = 1000 * 60; // 1 minute

        public DbData() {
            getFromDb();
        }    

        Object getData() {
            if(System.currentTimeMillis() - lastVisistToDB.get() > freshnessInterval) {
                getFromDB();
            }
            return dataFromDb;
        }

        private void getFromDb() {
            dataFromDb = getDataFromDb(...);
            lastVisistToDB.set(System.currentTimeMillis());
        }
    }

Note that if multiple "users" asking for data that is not fresh - you will be calling the DB multiple times. However once this has happened you are good for 1 minute or whatever the duration you set in freshnessInterval

David Soroko
  • 8,521
  • 2
  • 39
  • 51