Как включить кэш запросов Hibernate только на уровне сеанса? - PullRequest
6 голосов
/ 16 сентября 2009

Что если у меня есть запрос, который вызывается несколько раз в одном потоке, и я просто хочу кэшировать этот запрос (и его результат) для этого потока (или для этого сеанса, поскольку я использую один сеанс на поток) как я могу это сделать?

Примечание: мой кэш 2-го уровня включен, но в основном он используется для session.get (...). Но я не хочу использовать его для кеша запросов, потому что он мне нужен только на время работы моего потока (/ сеанса).

Спасибо

Ответы [ 3 ]

5 голосов
/ 16 сентября 2009

Суть в следующем: вы можете либо вручную кэшировать результаты запроса, либо вы можете попросить Hibernate сделать это. Хотя обычно не имеет смысла ограничивать время жизни кэша запросов до сеанса, это можно сделать, используя следующий подход:

1) Включить кэш запросов

2) Выделите конкретный регион для рассматриваемого запроса и отметьте его как кешируемый:

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

3) Извлеките свой запрос из кэша в конце сеанса (если вы ДЕЙСТВИТЕЛЬНО уверены, что это именно то, что вы хотите сделать):

SessionFactory sessionFactory = ...;
sessionFactory.evictQueries("MY_SPECIAL_QUERY");
2 голосов
/ 16 сентября 2009

Кэширование запросов не может быть применено к кешу сеансов. Это имеет смысл, поскольку, как правило, все операции с сеансом выполняются одним фрагментом кода, который должен просто помнить сами результаты.

Вы говорите, что не хотите включать кэширование запросов 2-го уровня, но какой вред это сделает? Вы получите желаемый результат.

0 голосов
/ 16 сентября 2009

Я не знаю ни одной подобной функции для Hibernate.

Но это кажется очень ограниченным и управляемым контекстом. Я хотел бы попытаться сделать это код. На первый взгляд возможны различные способы:

  • Если ваш код хорошо известен, сложность поддается управлению. Предположим, у вас есть код A, который вызывает коды B и C, оба они нуждаются в запросе. Вы можете выполнить запрос один раз в A, так как передает результат в B и C . Может быть, у вас уже есть объект контекста, который вы отправляете в B и C? Это было бы просто, изящно, значимо ...
  • Предположим противное: ваш код - настоящий беспорядок, и вы не можете передать контекст. У вас может быть переменная ThreadLocal, которая содержит результат . Если не установлено внутри текущего потока, вызовите его и сохраните. В противном случае просто получите его.

    Обратите внимание, что во втором случае вам придется позаботиться о чистке ThreadLocal при выходе из дома.

  • Между этими противоположностями возможны решения, одно из которых, вероятно, лучше других ...

...