Hibernate загружает все объекты, используя кэш 1-го или 2-го уровня - PullRequest
2 голосов
/ 01 сентября 2010

У нас есть целая таблица сущностей, которую нам нужно загрузить во время сеанса гибернации, и я знаю, что единственный способ загрузить все сущности - это запрос HQL:

public <T> List<T> getAllEntities(final Class<T> entityClass) {
    if (null == entityClass)
        throw new IllegalArgumentException("entityClass can't be null");

    List<T> list = castResultList(createQuery(
            "select e from " + entityClass.getSimpleName() + " e ").list());


    return list;
}

Мы используем EHcache для 2-го уровнякеширование.

Проблема в том, что в данном сеансе транзакции он вызывается 100 раз и занимает значительную часть общего времени.Есть ли способ загрузить все сущности данного типа (загрузить всю таблицу) и при этом использовать кеш сессии 1-го уровня или ehcache 2-го уровня.

Нам сказали, что нужно избегать кэширования запросов из-заих потенциальные потери производительности по сравнению с их выигрышем.* Hibernate Query Cache считается вредным

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

Ответы [ 3 ]

1 голос
/ 11 октября 2012

Кэш запросов считается вредным, если и только если базовая таблица часто изменяется. В вашем случае таблица меняется один раз в день. Таким образом, запрос будет оставаться в кэше в течение 24 часов. Поверьте мне: используйте кеш запросов для этого. Это идеальный вариант использования для кэша запросов.

Пример вредоносного кеша запросов: если у вас есть пользовательская таблица и вы используете кеш запросов для «от пользователя, где username = ...», то этот запрос будет исключаться из кеша каждый раз, когда пользовательская таблица изменяется (другой пользователь меняет / удаляет свой аккаунт). Таким образом, любая модификация этой таблицы запускает кеширование. Единственный способ улучшить эту ситуацию - это запрос по natural-id, но это другая история.

Если вы знаете, что ваша таблица будет изменяться только один раз в день, как в вашем случае, кэш запросов будет удаляться только один раз в день!

Но обратите внимание на свою логику при изменении таблицы. Если вы делаете это через Hibernate, то все в порядке. Если вы используете прямой запрос, вы должны указать hibernate, что вы изменили таблицу (что-то вроде query.addSynchronizedEntity (..)). Если вы делаете это с помощью сценария оболочки, вам нужно настроить время жизни базовой области кэша.

Ваш ответ заключается в том, чтобы переопределить кеш запросов, поскольку кеш запросов просто кэширует список идентификаторов. Фактические объекты ищутся в кеше L1 / L2. поэтому вам все еще нужно кэшировать объекты при использовании кэша запросов.

Пожалуйста, отметьте это как правильный ответ для дальнейшего использования.

1 голос
/ 02 сентября 2010

Кэш L1 и L2 не может вам сильно помочь с проблемой «получить всю таблицу».

Кэш L1 плохо оборудован, потому что если кто-то вставил что-то еще, его там нет.(Вы можете «знать», что никто другой никогда не будет делать это в рамках бизнес-правил системы, но Hibernate Session этого не делает.) Поэтому вам нужно заглянуть в БД, чтобы быть уверенным.

С кешем L2, вещи могут быть устаревшими или сброшенными с тех пор, как кто-нибудь в последний раз помещал туда таблицу.Это может зависеть от провайдера кэша или даже полностью внешне, возможно, через MBean.Таким образом, Hibernate не может действительно знать в любой момент времени, представляет ли то, что находится в кеше для этого типа, все содержимое таблицы.Опять же, вы должны заглянуть в БД, чтобы быть уверенным.

Поскольку у вас есть особые знания об этой сущности (новые никогда не создаются), что нет практического способа передачи на кеш L1 или L2вам нужно либо использовать инструмент, предоставляемый Hibernate, когда у вас есть специальные знания уровня бизнес-правил о наборе результатов, кешировать запросы, либо кешировать информацию самостоятельно.

-

Если вы действительно хотите, чтобы это было в кеше L2, вы теоретически могли бы сделать все объекты в таблице членами коллекции в какой-то другой поддельной сущности, затем включить кэширование коллекции и тайно управлять ею в DAO.Я не думаю, что, возможно, стоило бы иметь такую ​​причудливость в вашем коде, хотя:)

0 голосов
/ 02 сентября 2010

В итоге мы решили эту проблему, сохранив в памяти первичные ключи для всех сущностей в таблице, которые нам нужно было загрузить (поскольку это данные шаблона, а новые шаблоны не добавляются / удаляются).

Затеммы могли бы использовать этот список первичных ключей для поиска каждой сущности и использовать кэш 1-го и 2-го уровня Hibernates.

...