[RESOLVIDO]Count(*) do relacionamento @OneToMany

Olá pessoal do GUJ, estou com uma dúvida de como projetar na consulta do Hibernate a quantidades de ‘filhos’ de uma relação 1:N. Vamos as classes:

[code]public class Grupo{

private String nome;

@Transient
private int tamanhoListaSubgrupos, tamanhoListaItens;

@OneToMany(mappedBy = “grupo”, fetch = FetchType.LAZY)
private List subgrupos;

@OneToMany(mappedBy = “grupo”, fetch = FetchType.LAZY)
private List itens;

// get e set …
}

public class Item{

private String nome;

@ManyToOne @JoinColumn(name = “fk_grupo”)
private Grupo grupo;

//get, set e outros atributos
}

public class Subgrupo{

private String nome;

@ManyToOne @JoinColumn(name = “fk_grupo”)
private Grupo grupo;

//get, set e outros atributos
}[/code]

O problema começa quando eu tenho que listar os grupos, porque na view além de ser exibida as informações do Grupo, eu também tenho que exibir a quantidade de itens e subgruupos associados a ele. O select para isso é esse:

select g.id as id_grupo, g.nome as nome_grupo, (select count(*) from subgrupos s where g.id = s.fk_grupo) as total_subgrupos, (select count(*) from itens i where g.id = i.fk_grupo) as total_itens from grupos g
Como estou usando o hibernate eu fiz desse jeito:

[code]public List all() throws Exception {

	Criteria c = session.createCriteria(Grupo.class,"g")
	.setProjection(Projections.projectionList()
					.add(Projections.property("g.id").as("id") )
					.add(Projections.property("g.nome").as("nome") ) )
							
	.setResultTransformer(new AliasToBeanResultTransformer(Grupo.class) );
	
	List<Grupo> lista = c.list();
	for(Grupo g : lista){
		
		g.setTamanhoListaItens(getTotalItensGrupo(g.getId()));
		g.setTamanhoListaSubgrupos(getTotalSubgrupoGrupo(g.getId()));
	}
	return lista;	

}[/code]

Reparem que na primeira parte do método eu projeto os campos do Grupo, depois da lista gerada, eu a percorro e chamo os métodos getTotalItensGrupo(long id) e getTotalSubgrupoGrupo(long id) que retornam a quantidade de itens e subgrupos respectivamente associados ao Grupo. Tá funcionando perfeitamente, mas fica parecendo um POG :smiley: . Minha pergunta é essa: como projetar diretamente com o Criteria o count(*) da relação @OneToMany?

Abraço a todos.

Jonh Paulo

Não testei mas, deve ser a mesma coisa que no SQL, você vai usar a projeção(funções de agregação) com os campos e depois você tem que fazer um group by…

Se não for assim, deve haver um jeito, porque fica gambiarresco mesmo…

Depois de muito procurar achei uma solução: a anotação @Formula do hibernate http://gokhan.ozar.net/hibernate-derived-properties-formula-annotation/
Minhas classes ficaram assim:

[code]public class Grupo {

private String nome;

@Formula("(select count(*) from subgrupos s where s.fk_grupo = id)")
private int tamanhoListaSubgrupos; 

@Formula("(select count(*) from itens i where i.fk_grupo = id)")
private int tamanhoListaItens;

    //get e set

}

   // e o DAO
public List<Grupo> all() throws Exception {
	
	Criteria c = session.createCriteria(Grupo.class,"g")
	.setProjection(Projections.projectionList()
					.add(Projections.property("g.id").as("id") )
					.add(Projections.property("g.nome").as("nome") )
					.add(Projections.property("g.tamanhoListaSubgrupos").as("tamanhoListaSubgrupos") )
					.add(Projections.property("g.tamanhoListaItens").as("tamanhoListaItens") ))
							
	.setResultTransformer(new AliasToBeanResultTransformer(Grupo.class) );
	
	return c.list();	
}[/code]

Funcionou exatamente do jeito que eu queria. O SQL gerado foi esse aqui:

select this_.id as y0_, this_.nome as y1_, (select count(*) from subgrupos s where s.fk_grupo = this_.id) as y2_, (select count(*) from itens i where i.fk_grupo = this_.id) as y3_ from grupos this_

Abraços a todos

Jonh Paulo