[RESOLVIDO] setFetchMode JOIN "não funciona"

Ola Pessoal.
Estou com o seguinte problema.
Tenho 3 classes (Contratos, Clientes e Faturamento ).

O mapeamento de relacionamento da classe Faturamento com Contratos

@ManyToOne(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
@JoinColumns({
	@JoinColumn (name="CONTRATO", referencedColumnName="CONTRATO", insertable=false, updatable=false),
	@JoinColumn (name="FILIAL", referencedColumnName="FILIAL", insertable=false, updatable=false)
})
private Contratos contratos;`

Dentro de Contratos tenho o relacionamento com Clientes

@ManyToOne(cascade = {CascadeType.ALL}, fetch = FetchType.LAZY)
@JoinColumns({
	@JoinColumn (name="CLIENTE", referencedColumnName="CLIENTE", insertable=false, updatable=false),
	@JoinColumn (name="LOJA", referencedColumnName="LOJA", insertable=false, updatable=false)
})
private Clientes cliente;`

Quando vou efetuar uma consulta na class Faturamento , me deparei com o problema de varios selects (O Famoso SELECT N+1).

Criteria select = session.createCriteria(Contratos.class);
select.setFetchMode("cliente", FetchMode.JOIN);
contratos = select.list();`

Tentei efetuar a consulta utilizando setFetchMode.JOIN, porem não ouve nenhuma mudança.

O que mais posso estar vacilando?

No aguardo de uma ajuda

Não lembro muito bem desse maquinário do Hibernate, mas parece que faltou você atribuir:

select = select.setFetchMode(“cliente”, FetchMode.JOIN);

Dependendo do caso fica melhor você escrever como neste exemplo:

  List<Item> items = session.createCriteria(Item.class)
                    .setFetchMode("bids", FetchMode.JOIN).
                    .createAlias("bids", "b").
                    .add(Restrictions.gt("b.amount", 100)).
                    .list();

No mais, posta o SELECT que o Hibernate está gerando N selects.

javaflex, Queria que fosse só isso! Mas ja tentei a sintaxe de varias formas, inclusive como mencionado.

Estou ainda tentando… caso eu ache a solução, compartilho aqui com vocês!

Uma coisa que reparei…

O JOIN esta sendo montado corretamente, mas mesmo assim ele teima em executar as outras selects desnecessárias.

utilizando HQL tbm apresenta o problema de SELECT N+1 , mesmo usando fetch

Query query = session.createQuery("from Contratos c join fetch c.cliente cli where c.filialHigienizacao=:filialHigienizacao " + "and c.moduloCoala=:moduloCoala and c.mapaProducao!=:mapaProducao and c.situacaoContrato!=:situacaoContrato " + "and c.segmento!=:segmento and c.deleted=:deleted"); query.setString("filialHigienizacao",filialHigienizacao); query.setString("moduloCoala","02"); query.setString("mapaProducao","D"); query.setString("situacaoContrato","N"); query.setString("segmento","400003"); query.setString("deleted", ""); contratos= query.list();

Se o join do SQL gerado pelo hibernate está correto então pode ser outra associacao gerando n querys.

Se está sendo obrigado a usar hibernate, vai se acostumando que é assim mesmo, perde-se tempo pra algo que se fosse SQL nativo não teria nenhum mistério.

Qual a query gerada pelo Hibernate? Qual a entidade da query N+1?

sindronio, a entidade que esta gerando N+1 é de clientes.

Fiz uma simples consulta na entidade Contratos e gera varios select na entidade Cliente.

Dentro da N+1 do cliente ele traz a entidade Loja também?

Na verdade LOJA não é uma entidade, é um atributo da entidade Cliente

Ele monta a primeira query com o JOIN e em seguidas N select de acordo com a quantidade de registro.

` select
campos contratos…,
campos clientes
from
Contratos this_
inner join
Clientes c1_
on this_.CLIENTE=c1_.CLIENTE
and this_.LOJA=c1_.LOJA
where

select
campos clientes
from
Clientes clientes0_
where
clientes0_.CLIENTE=?
and clientes0_.LOJA=? `

Entendi, pensei que Loja fosse entidade e que na query Cliente viesse como Join.
Já retirou essa @JoinColumn de Loja para testar?

1 curtida

Cara… Funcionou!

Mas e agora? estas tabelas apenas se ligam por essas chaves, ou seja, irá existe o mesmo cliente em loja diferentes e isso poderá acarretar em uma join incorreto…

Pois é.
O que acho que aconteceu ai é que o Hibernate tenta mapear Loja como se fosse uma Entidade.

Se Cliente tem um atributo loja que o identifique este deve estar no seu Id, como uma chave composta.

Assim, na hora que for feito a query automaticamente ele irá buscar um Cliente utilizando o código e loja como parâmetro.

1 curtida