Почему этот FetchType.LAZY игнорируется и все объекты выбираются в запросе? - PullRequest
1 голос
/ 17 октября 2019

Я использую Spring Boot 2 с Hibernate, и у меня есть объект с именем ItemCarga с этим:

@ManyToMany(cascade = { CascadeType.DETACH }, fetch = FetchType.LAZY)
@JoinTable(name = "rel_transp_carga", joinColumns = { @JoinColumn(name = "fk_item_carga") }, inverseJoinColumns = { @JoinColumn(name = "fk_transportadora") })
@LazyCollection(LazyCollectionOption.TRUE)
private Set<Transportadora> transportadoras = new HashSet<Transportadora>();

Whey делает запрос с использованием этого объекта в моем хранилище, например:

@Query("select e from ItemCarga e where e.cnpjCeramica = :cnpjCeramica and (e.dataInserido between :inicio and :fim) ")
List<ItemCarga> listarProdutosPorPeriodo(
        @Param("cnpjCeramica") String cnpjCeramica, 
        @Param("inicio") Date dataInicial, 
        @Param("fim") Date dataFinal, 
        Sort sort);

Результатом является набор ItemCarga сущностей с атрибутом transportadoras, выбранных со всеми его элементами.

Разве это не должно быть нулем или пустым?

Не следует ли игнорировать, так как я не упомянул этот атрибут в моем выборе?

1 Ответ

1 голос
/ 17 октября 2019

Вы упомянули атрибут в запросе: select e from ItemCarga e. Это означает, что вы получаете целую ItemCarga сущность. Поскольку вы определили transportadoras как fetch = FetchType.LAZY, создается прокси (данные не извлекаются из базы данных).

Если вы вызываете запрос с транзакцией, вы можете выполнить итерацию по набору, тогда hibernate извлечет дочерние объекты (это часто приводит к проблеме выбора n + 1). Если вы попытаетесь получить доступ к нему вне транзакции, будет выдано LazyInitializationException.

Поскольку это всего лишь подсказка для спящего режима, вы можете убедиться, что Set не будет получен несколькими способами:

  1. , не запрашивая его, например:

    @Query("select e.field1, e.field2 from ItemCarga e ...")
    List<Object[]> listarProdutosPorPeriodo...
    

    Недостатком является то, что вы должны разыграть результаты,

  2. с использованием dto и сопоставления запросов. Я не буду описывать это подробно, более подробно вы можете найти здесь ,

  3. , используя проекции - интерфейсы с геттерами и сеттерами для полей, которые вы хотите получить. Подробнее здесь .

...