Francisco Souza
Francisco Souza

Reputation: 828

Why is this FetchType.LAZY being ignored and all entities are being fetched on the query?

I am using Spring Boot 2 with Hibernate and I have an entity named ItemCarga with this:

@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 do a query using that entity on my repository, like this:

@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);

The result is a set of ItemCarga entity with the attribute transportadoras fetched with all its items.

It shouldn't it be null or empty?

Shouldn't be ignored since I didn't mention that attribute on my select?

Upvotes: 1

Views: 352

Answers (1)

Andronicus
Andronicus

Reputation: 26076

You did mention the attribute in the query: select e from ItemCarga e. This means you're fetching the whole ItemCarga entity. Since you defined transportadoras as fetch = FetchType.LAZY, a proxy is created (the data is not fetched from the database).

If you're invoking the query withing transaction, you can iterate over the set, then hibernate will fetch the child entities (this often leads to n+1 select problem). If you try to access it outside of transaction, LazyInitializationException will be thrown.

Since it's just a hint for hibernate, you can make sure, the Set won't be fetched in a couple of ways:

  1. by not querying for it, for example:

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

    The downside is that you have to cast the results,

  2. by using dto and query mapping. I won't describe it in detail, more you can find here,

  3. by using projections - interfaces with getters and setters for the fields you want to fetch. More details here.

Upvotes: 1

Related Questions