How to enable hibernate query cache on a session level only?
Asked Answered
L

3

6

What if I have a query that gets called multiple times in a single thread, and I just want to cache that query (and its result) for that thread (or for that session since I'm using one session per thread), how can I do that ?

Note: My 2nd level cache is turned on but it's used mostly for session.get(...). But I do not want to use it for my query cache because I only need it to live for the duration of my thread ( / session ).

Thanks

Lactation answered 16/9, 2009 at 12:40 Comment(0)
S
5

The bottom line here is: you can either manually cache your query results or you can ask Hibernate to do it. While it generally makes little sense to restrict your query cache lifetime to that of session, it can be done using the following approach:

1) Enable query cache

2) Dedicate a specific region for query in question and mark it as cacheable:

Query query = ...;
query.setCacheable(true).setCacheRegion("MY_SPECIAL_QUERY");

3) Evict your query from cache at the end of the session (if you're REALLY sure that's what you want to do):

SessionFactory sessionFactory = ...;
sessionFactory.evictQueries("MY_SPECIAL_QUERY");
Steger answered 16/9, 2009 at 15:27 Comment(0)
S
2

Query caching cannot be applied to the session cache. This makes sense, since generally all operations against a session are done by one piece of code, which should just be able to remember the results itself.

You say you don't want to enable 2nd-level query caching, but what would be the harm in doing so? You'd get your desired results.

Spirogyra answered 16/9, 2009 at 13:32 Comment(2)
Because of darren.oldag.net/2009/05/… and other warnings out there. Also, I really don't have any reason keeping it alive for more than the duration of my thread.Lactation
+1. I've provided some details below on how to limit query cache lifetime to that of session (or other duration of your choosing) but I completely agree with skaffman - you must have a VERY special case for this to make sense.Steger
C
0

I don't know of any such feature for Hibernate.

But this seem to be a very limited and manageable context. I would try to do that is the code. Various ways seem possible at first sight:

  • If your code is well known, the complexity is manageable. Suppose you have a code A, that calls codes B and C, both of them need the query. You can run the query once in A, as pass the result to B and C. Maybe you already have a context object that you send to B and C? That would be simple, elegant, meaningfull...
  • Suppose the opposite, that your code is a real mess, and you can't pass a context around. You could have a ThreadLocal variable that contains the result. If not set inside the current thread, call it and store it. Otherwise, just retrieve it.

    Note that, in the second case, you would have to take care of cleaning the ThreadLocal when going out.

  • Between these opposites, solutions are possible, one of them is probably better than others...

Cohdwell answered 16/9, 2009 at 13:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.