Коллекции загружаются, даже если они объявлены как отложенные

#hibernate #jpa

#спящий режим #jpa

Вопрос:

 @Entity 
public class User {

    @ManyToMany(cascade = { MERGE, PERSIST, CascadeType.REFRESH }, fetch = LAZY)
    @Cache(usage = READ_WRITE)
    @UserRoles
    private List<Role> roles = new ArrayList<Role>(0);

}
  

Коллекции загружаются, даже если они объявлены как отложенные, что может быть причиной того, что они загружаются, даже если они объявлены как отложенные

Комментарии:

1. @axtavt: Хороший звонок! Когда Hibernate был новым и необычным, я видел, как простой метод toString (), используемый для ведения журнала отладки, практически останавливал систему, вызывая сотни операций чтения базы данных.

2. @axtavt — В журналах моей консоли с сервера jboss отображаются инструкции sql, которые указывают, что они загружаются.

Ответ №1:

Согласно спецификации JPA 2.0, отложенная выборка — это подсказка поставщику сохраняемости.

В разделе 11.1.6 говорится:

Стратегия ОЖИДАНИЯ — это требование среды выполнения поставщика сохраняемости, согласно которому данные должны извлекаться с готовностью. Отложенная стратегия — это подсказка для среды выполнения поставщика сохраняемости, что данные должны извлекаться лениво при первом обращении к ним.Реализации разрешено оперативно извлекать данные, для которых была указана подсказка по ОТЛОЖЕННОЙ стратегии.

Бывают случаи, в которых поставщик может решить, что нет смысла лениво извлекать что-либо, или, возможно, поставщик может даже не реализовать отложенную выборку.

Методы PersistenceUtil.isLoaded могут использоваться для определения состояния загрузки объекта и его атрибутов независимо от единицы сохранения, с которой связан объект.

Чтобы быть уверенным, что вы сталкиваетесь с такого рода проблемами, вам следует использовать этот метод. Конечно, если объект был отсоединен, простая проверка поля, извлеченного лениво, также могла бы помочь.

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

[РЕДАКТИРОВАТЬ-1]

Существует также проблема с отложенной загрузкой, если вы используете классы final. В документации Hibernate говорится, что в разделе постоянные классы:

Центральная функция Hibernate, прокси, зависит от того, является ли постоянный класс либо не окончательным, либо от реализации интерфейса, который объявляет все общедоступные методы.

Вы можете сохранить конечные классы, которые не реализуют интерфейс с Hibernate. Однако вы не сможете использовать прокси для отложенной выборки ассоциаций, что в конечном итоге ограничит ваши возможности по настройке производительности.

Вам также следует избегать объявления общедоступных конечных методов в не-конечных классах. Если вы хотите использовать класс с общедоступным методом final, вы должны явно отключить прокси, установив lazy=»false».

[РЕДАКТИРОВАТЬ-2]

Кроме того, в спецификации JPA 2.0 в разделе 2.1 указано, что объекты не должны быть окончательными:

Класс сущности не должен быть окончательным. Никакие методы или постоянные переменные экземпляра класса entity не могут быть окончательными

Это же требование позже указано для встраиваемых файлов в разделе 2.5.

У меня нет доступа к спецификации JPA 1.0, но я вполне уверен, что это требование применимо и к ней. Попробуйте и посмотрите, является ли это причиной, и дайте нам знать.

Комментарии:

1. Я использую ehcache в качестве кэша 2-го уровня

2. @Joe Возможно, вы захотите проверить использование конечных классов в вашей модели, несмотря на то, что они противоречат требованиям спецификации JPA 2.0, у нее также есть проблемы с отложенной загрузкой в режиме гибернации. Я соответствующим образом обновил сообщение. Случайно вы используете классы final для каких-либо отношений в вашей модели, более конкретно для рассматриваемых отношений, которые не извлекаются лениво?

3. Я использую Hibernate 3.3.x, который совместим с JPA 1.2

4. У меня есть окончательные квалификаторы в получателях и установщиках, это проблема?

5. @Joe Ну, в спецификации JPA указано, что ни класс, ни поля, ни его методы не должны быть окончательными. У меня нет доступа к спецификации JPA 1.0, но я вполне уверен, что это требование применимо и к ней. Попробуйте и посмотрите, является ли это причиной, и дайте нам знать.