3

I have an entity (JPA annotations with Hibernate query interface) which has a composite business key of two properties (an external-id and a subsidiary-id [that's a foreign key]) and a primary db key.

I have a JavaSE multi-threaded process which runs "with respect to a subsidiary" and needs to query/update/insert those entities using that composite key (it gets datasets of those external-ids).

I can guarantee that once such a process loads no other process will try to insert/update/remove that subsidiary.

What I want is to load all existing entities of that subsidiary on startup and then have every query for a pair of [externalId,subsidiaryId] to go through the cache and only if there's a miss to go through the db. In case one of the threads from the process inserts an entity I of course want that to be added to that cache.

What's the best course of action?

I know there's query caching but from what I can gather that will still be a miss the first time of every [externalId,subsidiaryId] pair.

Thanks and if there's anything which I'm not clear about please ask

Update
I had to stop investigating this issue but now that I've come back to it I think that it's seems reasonable that only the query cache and JB Nizet's answer are the only ones applicable.
I'll accept JB Nizet's answer as it is interesting and I might use it (not sure yet).

Ittai
  • 5,625
  • 14
  • 60
  • 97

1 Answers1

2

I would use a second-level cache for the entity, query for all the subsidiry's entities at startup (this will fill the second-level cache), and initialize an application cache which would just map [externalId, subsidiaryId] to [id].

Then, each time you're searching for an entity with a given [externalId, subsidiaryId], first get its ID from the application cache, then

  • if the ID is not in the cache, execute the query, update the application cache, and return the found entity
  • if the ID is in the cache, get the entity using its ID, which will go to the second-level cache and avoid hitting the DB
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Hi JB Nizet, thanks for your comment. Your suggested course of action entails the cache maintenance, right? Since my multi-threaded app adds these entities as it goes along. The advantages of using the ORM's facade for cache for me was so that I don't need to enter additional handling for these cases. If this is the only option I have I'm thinking maybe I'm better off with the query cache. I'd love to hear if you think there is a different way within the ORM facede to do this. – Ittai Nov 23 '11 at 06:10
  • I don't think there is a different way. The query cache can only be populated by executing queries, and these queries will first go to the database if the're not cached yet. – JB Nizet Nov 23 '11 at 07:42
  • Yeah, I know there isn't a different way with respect to the query cache itself, I was hoping for a different way with respect to the entity cache. Something like defining for it to also look for the [externalId, subsidiaryId] pair when it misses on the id before going to the db. – Ittai Nov 23 '11 at 09:00