Fetch Type LAZY по-прежнему вызывает жадную загрузку данных Hibernate Spring

Я создал простой загрузочный проект Spring с данными Spring.

У меня есть объект TagGroup, который имеет отношение один ко многим с тегами.

 @Entity
 @Table(name = "TAG_GROUP")
 public class TagGroup{

  @OneToMany(fetch=FetchType.LAZY,mappedBy = "tagGroup")
  private Set<Tag> tagList;

 }

Объект тега показан ниже.

  @Entity
  @Table(name = "TAGS")
  public class Tag {

      @ManyToOne(optional = false,fetch=FetchType.LAZY)
       @JoinColumn(name = "TAG_GROUP_ID")
       private TagGroup tagGroup;

  }

Я использую данные Spring, расширяющие JPArepository и использующие его метод findAll.

Проблема в том, что ленивая выборка не работает, НО на самом деле она загружает список тегов также без явного вызова tagList, как если бы это было EAGER...

Может ли кто-нибудь сказать мне, что я делаю неправильно здесь?


person DragonZoned    schedule 29.03.2016    source источник
comment
Можете ли вы показать метод/класс, в котором вы извлекаете этот объект и ожидаете исключение LazyInitialization.   -  person Madhusudana Reddy Sunnapu    schedule 29.03.2016
comment
Дело не в том, что я ожидаю ленивого исключения инициализации. Просто поведение нетерпеливо, когда оно должно быть ленивым. Я использую стандартную структуру MVC. Интерфейс данных Spring автоматически подключается к службе, которую вызывает контроллер. Кроме того, как я уже сказал, это загрузочный проект Basic Spring и ничего более здесь.   -  person DragonZoned    schedule 29.03.2016


Ответы (1)


Это из-за свойства spring.jpa.open-in-view=true.

Согласно spring-boot-configuration Приложения с загрузкой Spring используют spring.jpa.open-in-view=true.

С этим свойством он

Зарегистрируйте OpenEntityManagerInViewInterceptor. Привязывает JPA EntityManager к потоку для всей обработки запроса.

Таким образом, в вашем случае впоследствии, когда вы вызываете getTagList(), то есть извлекаете tagList, он впоследствии запускает другой запрос для получения tagList, поскольку EntityManager все еще открыт.

Как вы, возможно, знаете, LazyInitializationException никогда не выбрасывается, если entityManager, загрузивший родителя, все еще открыт.

Чтобы переопределить это, вы можете добавить spring.jpa.open-in-view=false в свой application.properties/application.yml, после чего вы должны увидеть LazyInitializationException.

person Madhusudana Reddy Sunnapu    schedule 29.03.2016
comment
Извините, Мадхусудана, spring.jpa.open-in-view=true должен сохранить тот же EntityManager для текущего веб-запроса, чтобы избежать исключения ленивой инициализации, которого я все равно не получаю !!! Так что, пожалуйста, забудьте эту часть. Возможно Вы неправильно прочитали вопрос, я перефразировал свой вопрос. Пожалуйста, перечитайте его. - person DragonZoned; 29.03.2016
comment
@DragonZoned Думаю, я понял. Таким образом, вы не вызываете tagList явно по-прежнему объекты tagList. Это интересно. Не могли бы вы опубликовать запросы sql, которые запускаются при вызове findAll. - person Madhusudana Reddy Sunnapu; 29.03.2016
comment
@DragonZoned Согласно отображению, он должен быть ленивым. Я подозреваю, что tagList вызывается неявно или toString() из TagGroup. Чтобы исключить такую ​​возможность, так как я думаю, что вы должны вызывать метод findAll() из какого-то класса service, можете ли вы поставить System.out.println("Loaded Taggroup") сразу после той строки, где вы вызываете метод findAll(). Если мы видим, что какой-либо select запрос запускается для извлечения списка тегов после вышеуказанного sysout, мы можем, по крайней мере, быть уверены, что загрузка tagList не является EAGER и bcos какого-то неявного вызова, который происходит позже. - person Madhusudana Reddy Sunnapu; 29.03.2016
comment
Получил проблему. Проблема заключается в сериализации, когда я отправляю список в ответ от контроллера. Бин модели вызывает список тегов во время сериализации, что вызывает проблему. Либо мне понадобится способ избежать спящего режима, вызывающего список тегов при сериализации, либо использовать объект представления для заполнения свойств модельного компонента и отправки его в ответ. - person DragonZoned; 29.03.2016
comment
@DragonZoned Это круто. Является ли это сериализацией JSOn, если да, вы можете рассмотреть возможность использования @JsonIgnore. - person Madhusudana Reddy Sunnapu; 29.03.2016
comment
С JsonIgnore я не смогу получить доступ к TagList в пользовательском интерфейсе, несмотря ни на что. вроде бы бессмысленно помещать taglist в боб в первую очередь ... - person DragonZoned; 30.03.2016
comment
используйте @JsonView, чтобы определить, когда сериализовать, а когда нет - person f.khantsis; 19.01.2017
comment
Мадхусудана Редди, спасибо, мне помогло. Как и большинство проблем, связанных со спящим режимом, ответ StackOverflow работает для одного из 15 человек. Так что я не удивлен, прочитав комментарии. - person Все Едно; 28.08.2017