Hibernate não faz Join! [ RESOLVIDO ]

7 respostas
G

Não consigo fazer o hibernate fazer JOINS em uma listagem de dados.
O problema está no relacionamento, em todo o sistema está ok, mais nessa classe estou com problemas.

Tentei fazer o seguinte:

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinColumn(name = "formaCobrancaid")
	@Fetch(FetchMode.JOIN)
	private FormaCobranca formaCobranca;

	@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	@JoinColumn(name = "cadcftvid")
	@Fetch(FetchMode.JOIN)
	private Cliente cliente;

Mais ele continua fazendo um bloco de vários SELECTS para cada registro.

O que fazer?

7 Respostas

davidpaniz

Não entendi o problema direito. O que o Hibernate está fazendo e o que você gostaria que ele fizesse?

G

Ele está fazendo Vários SELECT para cada registro.

Eu gostaria que ele fizesse apenas 1 SELECT para cada registro e utilizasse JOIN, LEFT JOIN, etc…
Gostaria de melhorar a performance!

rodrigo_gomes

Não entendi. Seu relacionamento um-para-um. Então não tem milagre, para cada registro de uma entidade ele vai buscar a entidade relacionada.

G

Outro, exemplo parecido

para cada registro que imprimi na tela o hibernate faz o seguinte:

Hibernate: select cliente0_.cadcftvid as cadcftvid13_0_, cliente0_.nome_cadcftv as nome2_13_0_ from cadcftv cliente0_ where cliente0_.cadcftvid=?
Hibernate: select this_.pedidovendaid as y0_, this_.dt_pedidovenda as y1_, this_.vl_total_pedidovenda as y2_, this_.formacobrancaid as y3_, this_.vendedor1id as y4_ from pedidovenda this_ where this_.status_pedidovenda in (?, ?, ?) and this_.cadcftvid=?
Hibernate: select formacobra0_.formacobrancaid as formacob1_10_0_, formacobra0_.nome_formacob as nome2_10_0_ from formacobranca formacobra0_ where formacobra0_.formacobrancaid=?

Quando eu queria que ele fizesse apenas

SELECT pedidovenda.DT_PEDIDOVENDA, pedidovenda.VL_TOTAL_PEDIDOVENDA, pedidovenda.STATUS_PEDIDOVENDA,
formacobranca.NOME_FORMACOB, cadcftv.NOME_CADCFTV FROM PEDIDOVENDA
JOIN FORMACOBRANCA ON pedidovenda.FORMACOBRANCAID = formacobranca.FORMACOBRANCAID
JOIN CADCFTV ON cadcftv.CADCFTVID = pedidovenda.VENDEDOR1ID WHERE
pedidovenda.STATUS_PEDIDOVENDA IN ('?', '?', '?') AND pedidovenda.CADCFTVID = ?

Minha pergunta é:
Como faço para deixar EXPLICITO que eu quero que ele utilize JOIN?

davidpaniz

Quando você deixa explícito que o fetch é Lazy, ele só vai fazer o select quando realmente for precisar dos dados. Para resolver o seu caso, imagino que usar FetchType.EAGER, ou só tirar o fetch = FetchType.LAZY (O default para OneToOne já é eager) deve resolver.

G

Não resolveu! os dados estão ok, consigo personalizar no criteria quais quero ou não.

O que estou com dificuldades, é que preciso que ele traga os dados em apenas 1 SQL usando JOIN.
Não usando 3 SQL por registros, entende?

G

RESOLVIDO

Lendo a documentação no hibernate.org encontrei o que precisava:

  • You can switch to an immediate non-lazy second SELECT by setting lazy=“false” on a collection or single-valued association mapping.

  • You can switch to an immediate non-lazy second SELECT for all single-ended associations to a particular entity class by disabling lazy fetching of the target entity using <class … lazy=“false”>. This is only really useful if there are a small number of instances of the entity, and we expect to be able to pull them from the second-level cache.

These settings let you define what part of the persistent graph should be loaded at all times. The how defaults to fetch=“select”.

  • With fetch=“join” on a collection or single-valued association mapping, you will actually avoid the second SELECT (hence making the association or collection non-lazy), by using just one “bigger” outer (for nullable many-to-one foreign keys and collections) or inner (for not-null many-to-one foreign keys) join SELECT to get both the owning entity and the referenced entity or collection. If you use fetch=“join” for more than one collection role for a particular entity instance (in “parallel”), you create a Cartesian product (also called cross join) and two (lazy or non-lazy) SELECT would probably be faster.

A Segunda parte eu já tinha feito, transformando para annotations o que faltou foi o seguite:

@Proxy(lazy=false)
public class ContasReceber implements Serializable {

Agradeço a todos que tentaram ajudar :slight_smile:

Criado 17 de abril de 2008
Ultima resposta 18 de abr. de 2008
Respostas 7
Participantes 3