Dúvida com JOIN (Hibernate)

Oi Pessoal,

Sinceramente, nunca vi um projeto open source mais MAL documentado que o Hibernate! Putz!!! :frowning:

Seguinte… Um consulta HQL do Hibernate o qual retorne um objeto que faça referência a outro(s) [ tipo associação pai/filho ] retornará 10 objetos-pai [ quando existirem 10 objetos-filho diferentes ] mesmo que o objeto-pai seja o mesmo em todos os 10.

Isso eu vi que é seu comportamento normal (apesar de que, já que o pai possui um Set contendo referências a filhos, seria interessante retornar apenas um pai, e o Set conter os 10 filhos).

Acontece que dessa forma o código abaixo não funciona:

Produto produto;

for ( int i = 0; i < result.size(); i++ ) {
   produto = ( Produto )result.get( i );

   Iterator it = produto.getCodigoBarras().iterator();

   dtm.addRow( new Object[]
      {
         produto.getIdProduto(),
         ( ProdutoCodigoBarras )it.next() ).getCodigoBarras(),
         produto.getDescricao(),
         nf.format( produto.getPreco() )
      }
   );
}

Não funciona porque a chamada iterator() em cada incremento do laço for irá fazer referência sempre a primeira posição (lembre-se: isso aí está retornando 10 objetos-pai, os quais são iguais, e que cada um desse 10 objetos-pai possui 1 Set, com 10 objetos-filhos diferentes dentro).

Qual a forma mais elegante de exibir os diferentes códigos de barras para o mesmo produto. :?

Atenciosamente,

Paulo Oliveira

Cara, não entendi direito sua dúvida quanto ao Hibernate.

Bem, de qualquer maneira, você indentificou o problema corretamente: a cada iteração no laço, você recria o iterator, fazendo com que iterator.next() retorne o primeiro item sempre.

Mas então, não entendi o seu objetivo. Você quer, na realidade, adicionar uma linha ( addRow() ) pra cada código de barras de cada produto?
Se sim, então está faltando um laço for ai no meio:

Produto produto;

for ( int i = 0; i < result.size(); i++ ) {
   produto = ( Produto )result.get( i );

   for( Iterator iter = produto.getCodigoBarras().iterator(); iter.hasNext(); )
   {
   	ProdutoCodigoBarras pcb = ( ProdutoCodigoBarras ) iter.next();

   	dtm.addRow( new Object[]
   	   	{
   	   	   	produto.getIdProduto(),
   	   	   	pcb.getCodigoBarras(),
   	   	   	produto.getDescricao(),
   	   	   	nf.format( produto.getPreco() )
   	   	}
   	);
   }
}

E cara, acho que você está fazendo alguma coisa errada com o Hibernate. Até onde consigo ver, seria perfeitamente possível fazer um prateleira.getProdutos().get( 0 ).getCodigoBarras().get( 0 ).getCodigoBarras()

E pequena dica, ao fazer isso:

for( int i = 0; i < 10; i++ )
{
    int j = i;
}

A JVM é esperta o bastante para não instanciar 10 objetos ‘j’, então pode declarar as variáveis no escopo conveniente sem problemas :smiley:

Tentou usar distinct?
Paulo, coloca +/- a HQL que vc tá tentando.
Me parece que vc quer na verdade filtrar a coleção dos filhos.

Olá pessoal…

Respondendo primeiro ao LIPE

  1. Obrigado pela dica da declaração de variáveis no escopo do laço For. Já mudei meu código! :slight_smile:
  2. Se eu botar dois laços For minha JTable vai listar 100 produtos, quando, por exemplo, na verdade eu teria 1 produto (objeto pai) com 10 códigos de barras diferentes (objetos filho).

E respondendo ao Louds (mas também serve p/ ti, Lipe), aqui vai a HQL:

result = session.find( "select b.produto from tisc.multuspdv.beans.ProdutoCodigoBarras as b "
   + "where b.produto.id = ?", new Integer( id ), Hibernate.INTEGER );

Que equivale à seguinte instrução SQL:

SELECT p.id, cb.pcbr_codigo_barras, p.prod_descricao, p.prod_preco
  FROM tb_produto p LEFT JOIN tb_produto_codigo_barras cb
    ON cb.pcbr_produto = 4 WHERE cb.pcbr_produto = p.id

Que nesse exemplo retorna os seguintes dados (no console do PostgreSQL):

 id | pcbr_codigo_barras | prod_descricao | prod_preco 
----+--------------------+----------------+------------
  4 | 7891037000315      | Cond.Seda Dvs. |       5.20
  4 | 7891037144903      | Cond.Seda Dvs. |       5.20
  4 | 7891037144859      | Cond.Seda Dvs. |       5.20
  4 | 7891037004221      | Cond.Seda Dvs. |       5.20
  4 | 7891037145900      | Cond.Seda Dvs. |       5.20
  4 | 7891037010031      | Cond.Seda Dvs. |       5.20
  4 | 7891037009585      | Cond.Seda Dvs. |       5.20
  4 | 7891037004283      | Cond.Seda Dvs. |       5.20
  4 | 7981037002593      | Cond.Seda Dvs. |       5.20
  4 | 7891037002265      | Cond.Seda Dvs. |       5.20
  4 | 7891037008137      | Cond.Seda Dvs. |       5.20
  4 | 7891037145351      | Cond.Seda Dvs. |       5.20

Ou seja… Minha consulta HQL está correta, retorna esses mesmos dados. O problema é esse lance do Hibernate me retornar 10 objetos-pai idênticos cada um contendo 10 objetos-filho. Na verdade, pra mim seria mais útil que ele me retornasse apenas 1 objeto-pai contendo em um Set os 10 objetos-filho. Já que (segundo a documentação do Hibernate -> http://www.hibernate.org/74.html#A6) esse comportamento é normal, eu tenho que bolar uma forma elegante de fazer o laço, percorrer meu(s) produto(s) e acessar o(s) código(s) de barras de cada produto.

Preciso de ajuda! :?

Atenciosamente,

Paulo Oliveira

Acho que voce precisa fazer uma pesquisa na ordem inversa da relação usando distinct…