[ Hibernate ] TOP-N Query com HQL

11 respostas
Armitage

Finalmente consegui me entender com o hibernate… eu acho… mais ainda estou com um pequeno problema… preciso realizar uma busca que retorne apenas o primeiro registro encontrado…

fiz o seguinte :

Session session = factory.openSession();
List cliente = session.createQuery(“from com.sms.Cliente cliente”).setMaxResults(1).list();

Só que com o setMaxResults(1) da erro… sem ele me traz a lista certinha…

Alguma sugestão?

11 Respostas

TedLoprao

Qual é o erro?

Armitage
Hibernate: select * from ( select rownumber() over() as row_, cliente0_.contaa as contaa, cliente0_.agencia as agencia, cliente0_.dac10 as dac10, cliente0_.codservc as codservc, cliente0_.dtenvio as dtenvio, cliente0_.hrenv as hrenv, cliente0_.staenvio as staenvio, cliente0_.codtxt as codtxt, cliente0_.dddtec as dddtec, cliente0_.tel8 as tel8, cliente0_.operadra as operadra, cliente0_.dataatua as dataatua, cliente0_.dtcada as dtcada, cliente0_.ebusines as ebusines, cliente0_.ebusidat as ebusidat, cliente0_.horaalte as horaalte, cliente0_.horacada as horacada, cliente0_.txtcad as txtcad from DB2DESEN.CLIENTES cliente0_ ) as temp_ where row_ <= ?

16:41:34,896  WARN JDBCExceptionReporter:38 - SQL Error: -104, SQLState: 42601

6975 [main] WARN net.sf.hibernate.util.JDBCExceptionReporter  - SQL Error: -104, SQLState: 42601

6975 [main] WARN net.sf.hibernate.util.JDBCExceptionReporter  - SQL Error: -104, SQLState: 42601

16:41:34,896 ERROR JDBCExceptionReporter:46 - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

6975 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter  - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

6975 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter  - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

16:41:34,936  WARN JDBCExceptionReporter:38 - SQL Error: -104, SQLState: 42601

7015 [main] WARN net.sf.hibernate.util.JDBCExceptionReporter  - SQL Error: -104, SQLState: 42601

7015 [main] WARN net.sf.hibernate.util.JDBCExceptionReporter  - SQL Error: -104, SQLState: 42601

16:41:34,986 ERROR JDBCExceptionReporter:46 - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

7065 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter  - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

7065 [main] ERROR net.sf.hibernate.util.JDBCExceptionReporter  - [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

 

16:41:35,006 ERROR JDBCExceptionReporter:38 - Could not execute query

COM.ibm.db2.jdbc.DB2Exception: [IBM][CLI Driver][DB2] SQL0104N  An unexpected token "(" was found following "".  Expected tokens may include:  ", FROM INTO ".  SQLSTATE=42601

Este erro... aqui uso o DB2 7.2

Dialeto e Driver utilizado
hibernate.dialect net.sf.hibernate.dialect.DB2Dialect
hibernate.connection.driver_class COM.ibm.db2.jdbc.app.DB2Driver
Jair_Rillo_Junior

será que no DB2 suporta o setMaxResults?
pois usando Firebird não funcionou e o mesmo código com o mySQL funcionou perfeitamente

Armitage

Oi ManchesteR,

Fiz alguns testes estes dias e bem… de fato o DB2 não aceita o MaxResult… por que o Hibernate coloca “row_ <= 1” por exemplo e o DB2 desconhece este “comando”… o que ele conhece é o “FETCH FIRST 1 ROWS ONLY” então no lugar de usar :

Session session = factory.openSession&#40;&#41;; List cliente = session.createQuery&#40;&quot;from com.sms.Cliente cliente&quot;&#41;.setMaxResults&#40;1&#41;.list&#40;&#41;;

passei a usar :

String query = "SELECT &#123;cliente.*&#125; FROM TB_CLIENTES &#123;cliente&#125; WHERE cliente.status = '' FETCH FIRST 1 ROWS ONLY"; 
Session session = factory.openSession&#40;&#41;; 
Query q = session.createSQLQuery&#40;query, "cliente", Cliente.class&#41;;
List  clientes = q.list&#40;&#41;;

E pronto problema resolvido!

Jair_Rillo_Junior

“Armitage”:
Oi ManchesteR,

Fiz alguns testes estes dias e bem… de fato o DB2 não aceita o MaxResult… por que o Hibernate coloca “row_ <= 1” por exemplo e o DB2 desconhece este “comando”… o que ele conhece é o “FETCH FIRST 1 ROWS ONLY” então no lugar de usar :

Session session = factory.openSession&#40;&#41;; List cliente = session.createQuery&#40;&quot;from com.sms.Cliente cliente&quot;&#41;.setMaxResults&#40;1&#41;.list&#40;&#41;;

passei a usar :

String query = "SELECT &#123;cliente.*&#125; FROM TB_CLIENTES &#123;cliente&#125; WHERE cliente.status = '' FETCH FIRST 1 ROWS ONLY"; 
Session session = factory.openSession&#40;&#41;; 
Query q = session.createSQLQuery&#40;query, "cliente", Cliente.class&#41;;
List  clientes = q.list&#40;&#41;;

E pronto problema resolvido!

Que bom que funcionou, vou usar essa dica para trabalhar com o Firebird (pois no firebird se usa “first N” onde N é o numero de linhas do resultado

TedLoprao

Manchester, no caso do Firebird isso já ocorre, vc pode usar o setMaxResults que ele usará esta estrutura…

Lembre-se q fazendo isso vc está usando um sql hard coded no seu código e isso só vai funcionar para determinado banco…

Jair_Rillo_Junior

“TedLoprao”:
Manchester, no caso do Firebird isso já ocorre, vc pode usar o setMaxResults que ele usará esta estrutura…

Lembre-se q fazendo isso vc está usando um sql hard coded no seu código e isso só vai funcionar para determinado banco…

a última vez que eu tentei usar o setMaxResult deu problema… vou tentar denovo então pra verificar

TedLoprao

Só complementando, Armitage, se vc ver para o DB2 existe 3 dilects, o DB2Dialect, o DB2390Dialect e o DB2400Dialect…

Apenas o DB2Dialect utiliza aquela maneira q vc postou para fazer o setMaxResults… Os outros dois utilizam o “fetch first n results only”

Será q vc não está usando o dialect errado?

Espero ter ajudado!!

Fallow

Armitage

“TedLoprao”:
Manchester, no caso do Firebird isso já ocorre, vc pode usar o setMaxResults que ele usará esta estrutura…

Lembre-se q fazendo isso vc está usando um sql hard coded no seu código e isso só vai funcionar para determinado banco…

Infelizmente não dá para se ganhar todas… melhor ter um único select “amarrado” ao banco de dados do que retornar 30 mil registros (em média, na fase piloto do sistema) para se trabalhar só com o primeiro da lista… e bem… aqui não tem chance de mudar o banco de dados… e se por acaso mudar já deixe documentado que este “método”, no meu caso, tem que ser alterado e o porque.

TedLoprao

Ainda assim, eu daria uma olhada nos outros dialects, qualquer coisa, acho que vc pode implementar o seu sem muitos problemas… Dessa maneira não terá problemas se ocorrer essa troca de banco… E não precisará ser alterado o código fonte…

Fallow

Armitage

TedLoprao,

Eu não tinha pensado nisto!
Mudei o dialeto e funcionou ;o)

Muito obrigada!

<edit> Eu não tinha visto seu post sobre os dialetos antes… vi depois que já tinha enviado o post anterior </edit>

Criado 25 de agosto de 2004
Ultima resposta 30 de ago. de 2004
Respostas 11
Participantes 3