Hibernate Lazyloading не работает с методом @Transactional - PullRequest
0 голосов
/ 10 мая 2019

Я сталкиваюсь со столь обсуждаемым ""

. Я работаю над приложением с весенней загрузкой, используя hibernate.

Насколько я знаю, если атрибут сущности помечен какFetchType.LAZY, с необходимостью иметь сеанс Hibernate, чтобы иметь возможность инициировать соответствующий запрос для получения связанной сущности.

Ниже приведен метод, который извлекает список сущностей из родительской сущности:

@Transactional
public List<Portfolio> getSharedPortfolios(String userName){
    User user = userService.getUserActive(userName);
    List<Portfolio> sharedPortfolios = user.getSharedPortfolios();
    //logger.debug("Number of Shared Portfolios: " + sharedPortfolios.size());  <======
    return sharedPortfolios;
}

Метод getSharedPortfolios вызывается из контроллера и получает «org.hibernate.LazyInitializationException», затем пытается получить доступ к этому списку (PersistentBag)

Существо getSharedPortfolios метод, аннотированный аннотацией @Transactional, я ожидал, что при выполнении user.getSharedPortfolios () (sharedPortfolios - Lazy Fetch List) соответствующий список инициализируется.Но этого не происходит.

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

Нужно ли в этом случае явно инициализировать его с помощью EntityManager?

Большое спасибо.

Ответы [ 2 ]

1 голос
/ 10 мая 2019

При вызове List<Portfolio> sharedPortfolios = user.getSharedPortfolios(); значение, присвоенное sharedPortfolios, является ленивым прокси.

Если вы просто вернете sharedPortfolios и получите доступ к нему вне вашего @Transactional метода, вы получите LazyInitializationException

С другой стороны, если вы обращаетесь к sharedPortfolios в своем методе @Transactional, происходит инициализация, и вы возвращаете уже инициализированные данные.

ИМХО, что вы описываете, это ожидаемое поведение.

Существует несколько способов заставить выборку:

  • граф сущностей
  • jpql (fetch)
  • критерий запроса (выборка)
  • ручной доступ к переменной (как показано в вашем примере)

Или проверьте настройку spring.jpa.open-in-view=true

0 голосов
/ 10 мая 2019

Я не уверен, что это значит

"Метод getSharedPortfolios вызывается из контроллера"

, поэтому это может быть не ваш случай, но аннотация @Transactional не будет работать, если вы вызываете метод getSharedPortfolios из другого метода в том же классе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...