Problema com Hibernate HQL - GROUP BY

3 respostas
Rangel_Zutin

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:
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
ENTITY:
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()
}
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:
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();
		}
}
Valeu pessoal!

3 Respostas

Rangel_Zutin

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!

partenon

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.

Rangel_Zutin

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.

Criado 26 de junho de 2010
Ultima resposta 28 de jun. de 2010
Respostas 3
Participantes 2