Sinceramente, nunca vi um projeto open source mais MAL documentado que o Hibernate! Putz!!!
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. :?
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
Obrigado pela dica da declaração de variáveis no escopo do laço For. Já mudei meu código!
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):
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.