Problema com Hibernate HQL - GROUP BY

Amigos,

Estou levando uma surra da HQL.
Tenho minha classe AccountToPay (Entity) e quero fazer a soma (SUM) de todos os valores (AP.amount) agrupados fornecedor (SP.supplier) se a a conta esta paga ou nao (AP.paid) mas estou tendo a seguinte Exception. Seguem meus codigos. Qualquer ajuda ou comentario sao bem-vindos.

EXCEPTION:

[code]14:33:50,830 ERROR JDBCExceptionReporter:101 - ORA-00979: not a GROUP BY expression

Exception in thread “main” org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2231)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125)
at org.hibernate.loader.Loader.list(Loader.java:2120)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at uk.co.rangel.hibernate.dao.AccountToPayDAO.getAmoutAccountToPayGroupedBySupplierHQL(AccountToPayDAO.java:109)
at uk.co.rangel.hibernate.simulation.accountsupplier.TestAccountToPayByHQL.main(TestAccountToPayByHQL.java:32)
Caused by: java.sql.SQLException: ORA-00979: not a GROUP BY expression[/code]
ENTITY:

[code]import java.util.Calendar;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Lob;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;

@Entity
public class AccountToPay {

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
private Long id;
@Lob
private String description;
private Double amount;
@Temporal(TemporalType.DATE)
private Calendar paymentDate;
private boolean paid;
@ManyToOne
@Cascade(CascadeType.SAVE_UPDATE)
private Supplier supplier;

   //gets() and sets()

}[/code]
DAO:

@SuppressWarnings("unchecked") public List<Object[]> getAmoutAccountToPayGroupedBySupplierHQL(int max){ Query query = this.getDAO().getSession().createQuery("SELECT AP.supplier, AP.paid, SUM(AP.amount) " + "FROM AccountToPay AP " + "GROUP BY AP.supplier, AP.paid"); query.setMaxResults(max); return query.list(); }
TESTE:

[code]public static void main(String[] args) {
AccountToPayDAO accountToPayDAO = new AccountToPayDAO(HibernateUtil.getSession());
List<Object[]> listObject = accountToPayDAO.getAmoutAccountToPayGroupedBySupplierHQL(2);
for(Object[] eachObject : listObject){
Supplier supplier = (Supplier) eachObject[0];

		String situation;
		if((Boolean) eachObject[1]){
			situation = "PAID";
		} else {
			situation = "NOT PAID";
		}
		System.out.println(supplier.getName() + " - " + situation);
		System.out.println("Amount to Pay: " + eachObject[2]);
		System.out.println();
	}

}[/code]
Valeu pessoal!

Pessoal,

pelo que eu analisei, o Hibernate nao esta montando a query da maneira correta. Segue a query.

select accounttop0_.supplier_id as col_0_0_, accounttop0_.paid as col_1_0_, SUM(accounttop0_.amount) as col_2_0_, supplier1_.id as id1_, supplier1_.description as descript2_1_, supplier1_.name as name1_ from AccountToPay accounttop0_ inner join Supplier supplier1_ on accounttop0_.supplier_id=supplier1_.id group by accounttop0_.supplier_id , accounttop0_.paid

Nao entendi porque ele busca os campos supplier1_.description e supplier1_.name, mas pra fazer dessa maneira ele nao teria que agrupar esses campos? Estou usando HQL de maneira errada?

Obrigado!

Quando voce manda o Hibernate retornar um objeto (e nao suas propriedades individuais), o Hibernate na verdade faz um select no banco de dados pelas colunas individuais. Isso para garantir que a coluna X estara na posicao Y, de forma que ele consiga mapear fielmente.

Entao, uma saida que eu vejo para o seu caso eh mandar agrupar tambem pelos campos extras que o Hibernate especifica (supplier.id, description e name). Outra saida eh vc usar “native SQL query”, mas dai vc precisa usar um result transformer, para informar ao Hibernate como mapear o retorno da query.

Oi Paternon. Foi isso mesmo que eu fiz. Mandei agrupar os campos extras e deu tudo certo. Estou estudando Hibernate e tambem fiz o mesmo exemplo usando “native SQL query” e ResultTransformer. Porem estou tendo um outro problema quando uso setResultTransform passando como parametro o Transformers.aliasToBean, ao inves de passar um newResultTransformer.

Assim funciona:

Assim nao funciona:

E gera a seguinte Exception:

Exception in thread "main" org.hibernate.PropertyNotFoundException: Could not find setter for NAME on class uk.co.rangel.model.Employed at org.hibernate.property.ChainedPropertyAccessor.getSetter(ChainedPropertyAccessor.java:68) at org.hibernate.transform.AliasToBeanResultTransformer.transformTuple(AliasToBeanResultTransformer.java:87) at org.hibernate.hql.HolderInstantiator.instantiate(HolderInstantiator.java:92) at org.hibernate.loader.custom.CustomLoader.getResultList(CustomLoader.java:353) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125) at org.hibernate.loader.Loader.list(Loader.java:2120) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:312) at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1722) at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165) at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:175) at uk.co.rangel.hibernate.dao.EmployedDAO.getListEmployedByNativeSQLAndResultTransformer(EmployedDAO.java:87) at uk.co.rangel.hibernate.simulation.employed.GetListEmployedByNativeSQL.main(GetListEmployedByNativeSQL.java:21)

De qualquer maneira irei criar um novo topico soh pra isso. Obrigado pela forca.