Как включить кэш запросов Hibernate только на уровне сеанса?

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

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

Спасибо

3 ответа

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

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

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

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

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

SessionFactory sessionFactory = ...;
sessionFactory.evictQueries("MY_SPECIAL_QUERY");

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

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

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

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

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

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

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

Другие вопросы по тегам