JSF + hibernate com SQLQuery

Bom dia!!!

Minha classe DAO tem a seguinte consulta:

public List<Categorias> agrupaCategorias() { Query q = getSession().createSQLQuery(" SELECT categorias.NOME, Count(categorias.NOME) AS contador " + " FROM categorias INNER JOIN (perg_resp_vinculados INNER JOIN faq ON perg_resp_vinculados.ID_PERGUNTA = faq.ID) ON categorias.id = faq.categoria_ID " + " GROUP BY categorias.NOME; ") .addEntity(Categorias.class); return q.list(); }
chamada assim:

CategoriasDAO dao = new CategoriasDAO(); relatorioCategoria = dao.agrupaCategorias();

e o seguinte erro acontece:

Grave: Error Rendering View[/relatorioCategoria.xhtml] javax.el.ELException: /relatorioCategoria.xhtml @27,71 value="#{acompanhamentosBean.relatorioCategoria}": Error reading 'relatorioCategoria' on type br.com.bb.gefin.atendTel.controle.AcompanhamentosBean at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:114) at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:193) at javax.faces.component.ComponentStateHelper.eval(ComponentStateHelper.java:181) at javax.faces.component.UIData.getValue(UIData.java:557) at javax.faces.component.UIData.getDataModel(UIData.java:1297) at javax.faces.component.UIData.getRowCount(UIData.java:342) at org.primefaces.component.datatable.DataTable.calculatePage(DataTable.java:769) at org.primefaces.component.datatable.DataTableRenderer.encodeMarkup(DataTableRenderer.java:160) at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:85) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:883) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1659) at javax.faces.render.Renderer.encodeChildren(Renderer.java:168) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:853) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1652) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1655) at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1655) at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:399) at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131) at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:121) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:313) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at br.com.bb.gefin.filtro.HibernateSessionRequestFilter.doFilter(HibernateSessionRequestFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:928) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:539) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:298) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at java.lang.Thread.run(Unknown Source) Caused by: org.hibernate.exception.SQLGrammarException: could not execute query at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.loader.Loader.doList(Loader.java:2536) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) at org.hibernate.loader.Loader.list(Loader.java:2271) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316) at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842) at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165) at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157) at br.com.bb.gefin.atendTel.dao.CategoriasDAO.agrupaCategorias(CategoriasDAO.java:34) at br.com.bb.gefin.atendTel.controle.AcompanhamentosBean.getRelatorioCategoria(AcompanhamentosBean.java:927) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at javax.el.BeanELResolver.getValue(BeanELResolver.java:87) at com.sun.faces.el.DemuxCompositeELResolver._getValue(DemuxCompositeELResolver.java:176) at com.sun.faces.el.DemuxCompositeELResolver.getValue(DemuxCompositeELResolver.java:203) at org.apache.el.parser.AstValue.getValue(AstValue.java:169) at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189) at com.sun.faces.facelets.el.TagValueExpression.getValue(TagValueExpression.java:109) ... 43 more Caused by: java.sql.SQLException: Column 'ID' not found. at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956) at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926) at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144) at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2793) at com.mchange.v2.c3p0.impl.NewProxyResultSet.getInt(NewProxyResultSet.java:2573) at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$2.doExtract(IntegerTypeDescriptor.java:61) at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:64) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:253) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:249) at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:229) at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:330) at org.hibernate.loader.Loader.extractKeysFromResultSet(Loader.java:668) at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:606) at org.hibernate.loader.Loader.doQuery(Loader.java:829) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) at org.hibernate.loader.Loader.doList(Loader.java:2533) ... 61 more

sendo que minhas classes:

[code]
public class Categorias implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column (name="ID")
private Integer id;

@OneToMany(mappedBy="categoria")
private List<Faq> faq;

@Column (name="NOME", nullable=true, length=50)
private String nome;

@Column (name="CONTADOR")
private Long contador;

public class Faq implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column (name="ID")
private Integer id;

@ManyToOne
private Categorias categoria;

@Column (name="RESPOSTA", nullable=true)
@Type(type="text")
private String resposta;

@Column (name="PERGUNTA", nullable=true, length=255)
private String pergunta;

@Column (name="INC", nullable=true, length=100)
private String inc;

public class PergRespVinculados implements Serializable{

private static final long serialVersionUID = 1L;

@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column (name="ID")
private Long id;

//id faq

@Column (name="PERGUNTA", nullable=true, length=255)
private String pergunta;

@Column (name="RESPOSTA")
@Type(type="text")
private String resposta;

@ManyToOne
private Chamadas chamadas;

@Column (name="ID_PERGUNTA")
private Integer idPergunta;

@Column (name="SCRIPT_IGUAL_RESPOSTA")
private Boolean scriptIgualResposta;

@Column (name="SCRIPT_IGUAL_PERGUNTA")
private Boolean scriptIgualPergunta;[/code]

Tem ID onde pede ID…

Não sei o que está acontecendo, até pq quando eu faço o SQL no MYSQL direto, ele executa minha consulta.

Alguém sabe o que é isto?

Grato!!

Camarada, me parece que ele está implicando com o tipo de caixa utilizado.
Na query você define “categoria.id” como minúsculo e no mapeamento, “ID” maiúsculo.

É a única coisa que vejo ser diferente aí. Posso estar falando uma grande bobagem.

não é bobagem… mas é uma idéia!!

eu coloquei minusculo nele e depois no outro só pra tentar achar em qual dos dois ele estava reclamando, mas mesmo assim não localizei…

o erro sempre retorna que não achou o “ID” mesmo mudando p/ faq.id e categoria.id

a query original era toda maiuscula e não funciona…

Obrigado pela tentativa!

não lembro bem mas o createSQLQuery é o equivalente ao createNativeQuery do JPA certo? o addEntity é para retornar um objeto de Categorias certo? Se é para retornar um objeto de Categorias, mapeado pela base de dados, porque não tem uma coluna “ID” no retorno para ele saber qual “Categorias” é? Acho que é isso que ele está reclamando.

repare nessas linhas do erro:

Caused by: java.sql.SQLException: Column ‘ID’ not found.
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
at com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1144)
at com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2793)

verdade…
deve ser isto mesmo!!

mas o problema que se eu pedir pra retornar o id não da pra eu agrupar como eu quero… vou ter que criar uma classe só pra isso né?

não precisa criar uma classe só para isso (se não quiser). Você poderia, por exemplo, retornar na consulta um List<Object[]> (se não passar nenhuma classe)

Mas se quiser usar alguma classe, se me lembro bem você pode fazer algo assim:

public class Categorias{
 //seu código da classe
  public static class CategoriasCount{

    String name;
    Integer cont;

    public CategoriasCount(String name, Integer cont){
       this.name = name;
       this.cont = cont;
    }

  }
  // seu código da classe
}

E no HQL (essa consulta pode facilmente ser passada para HQL), você coloca assim:

  SELECT new Categorias.CategoriasCount(name, count(name))
  -- resto do seu SQL

Mas nunca trabalhei com Hibernate, só com EclipseLink, portanto não sei bem se é assim.

com outra classe eu resolvi…
fiz praticamente do jeito q você colocou sem o construtor

[code]public class RelatorioCategorias implements Serializable{

private static final long serialVersionUID = 1L;

private String nome;
private BigInteger contador;[/code]

só mudei o tipo pra BigInteger pois era o que vinha retornando da minha query…

e minha classe não é uma entidade, então usei um result transformer

public List<RelatorioCategorias> agrupaCategorias() { Query q = getSession().createSQLQuery(" SELECT categorias.NOME AS nome, Count(categorias.NOME) AS contador " + " FROM categorias INNER JOIN (perg_resp_vinculados INNER JOIN faq ON perg_resp_vinculados.ID_PERGUNTA = faq.ID2) ON categorias.ID2 = faq.categoria_ID " + " GROUP BY categorias.NOME " + " ORDER BY contador DESC;") ; //.addEntity(RelatorioCategorias.class); q.setResultTransformer(Transformers.aliasToBean(RelatorioCategorias.class)); return q.list(); }

Gostaria muito de usar a mesma classe, mas o problema que eu vejo de uma list<object[]> é que eu não consigo em uma página JSF(quando eu digo que não consigo, é que não sei se tem como e como faz…) chamar meus atributos…

hoje em dia é assim:

[code]<p:column sortBy="#{chamadas.nome}"
filterBy="#{chamadas.nome}"
filterMatchMode=“contains” style=“padding: 2px”>
<f:facet name=“header”>
<h:outputText value=“Categoria”/>
</f:facet>
<h:outputText value="#{chamadas.nome}" />
</p:column>

			<p:column sortBy="#{chamadas.contador}" style="padding: 2px;text-align:right">
				<f:facet name="header">
					<h:outputText value="Qtde. "/>
				</f:facet>
	            <h:outputText value="#{chamadas.contador}" />					
			</p:column>[/code]

pois eu tenho os alias de contar e nome, com a lista de object eu não sei como por pra chamar…