Duvida com query em Hibernate

2 respostas
andrerpbts

Olá pessoal,
Estou desde ontem pesquisando sobre como resolver meu problema, mas infelizmente não consegui, acredito que cheguei perto, mas sempre por um detalhe ou outro não funciona como o esperado.

Bom, para iniciar a Query que preciso fazer é a seguinte:

SELECT mn.*, count(m.id) as filhos
  FROM menu mn
  LEFT JOIN menu m
    ON mn.menu_id = m.id
 GROUP BY mn.id
 ORDER BY mn.ordem

Com ela pretendo retornar todos os registros da tabela menu, junto com a quantidade de registros que referencia cada um, pelo seu campo menu_id. Como segue a estrutura de meu Model:

public class Menu {
	@Id
	@GeneratedValue
	public Long id;
	public String descricao;
	public String link;
	public String titulo;
	public String ordem;
	@ManyToOne
	public Menu menu;
	public int nivel;
	@Transient
	public int filhos;
}

Não sei se fiz certo, mas criei um campo com annotation @Transient para que receba este valor no resultado da Query. Notem, que tenho um relacionamento para a mesma tabela (Menu) com annotation @ManyToOne. Fiz isto para que um registro possa conter um relacionamento de qual seria seu registro pai.

Com esta estrutura acima, eu estou tentando montar meu result, com o código:

Criteria c = session.createCriteria(Menu.class, "mn");
c.setProjection(Projections.projectionList()
	                   .add(Projections.groupProperty("mn.id"), "id")
	                   .add(Projections.property("mn.descricao"), "descricao")
	                   .add(Projections.property("mn.link"), "link")
	                   .add(Projections.property("mn.ordem"), "ordem")
	                   .add(Projections.property("mn.menu"), "menu")
	                   .add(Projections.property("mn.nivel"), "nivel")
	                   .add(Projections.count("m.id"), "filhos"));
c.createAlias("menu", "m", Criteria.LEFT_JOIN, Restrictions.eqProperty("m.menu.id", "mn.id"));
c.setResultTransformer(new AliasToBeanResultTransformer(Menu.class)); 
c.addOrder(Order.asc("ordem"));
return c.list();

O problema agora é que ao criar esta associação, por padrão o Hibernate está inserindo uma Restrição que no meu caso não pode ter, observe a query gerada:

select
        this_.id as y0_,
        this_.descricao as y1_,
        this_.link as y2_,
        this_.ordem as y3_,
        this_.menu_id as y4_,
        this_.nivel as y5_,
        count(m1_.id) as y6_ 
    from
        menu this_ 
    left outer join
        menu m1_ 
            on this_.menu_id=m1_.id
            and (
                m1_.menu_id=this_.id 
            ) 
    group by
        this_.id 
    order by
        y3_ asc

Sendo que a restrição padrão trata-se da linha:

Já procurei de várias maneiras para resolver o problema, mas não consigo, alguém pode me ajudar?

Se faltou alguma informação, por favor me falem que adiciono aqui.

Obrigado desde já…

2 Respostas

CintiaDR

Fofis, pode ser do jeito mais trivial?

Acho meio confuso mapear o menu pai ao invés da lista de filhos (essa coisa de recursão não é dos deuses rs). Eu faria ao contrário:

public class Menu {
	@Id
	@GeneratedValue
	public Long id;
	public String descricao;
	public String link;
	public String titulo;
	public String ordem;

	@OneToMany  //carrega essa lista por eager, fetch, ou qq coisa assim
	@OrderBy("ordem asc")  //não lembro a sintaxe, mas isso ajuda
	public List<Menu> submenus;

	public int nivel; // cuidado que essa informação é redundante, tenha certeza que está certa


	public getQuantidade(){
		return submenus.size();
	}
}

Busca basicamente todos os menus que vc quiser e só. Tem jeito de fazer ao contrário, mapeando o pai? Tem. Mas vc precisa?

andrerpbts

CintiaDR:
Fofis, pode ser do jeito mais trivial?

Busca basicamente todos os menus que vc quiser e só. Tem jeito de fazer ao contrário, mapeando o pai? Tem. Mas vc precisa?

O problema que hoje já tenho o menu todo funcionando da forma que deveria, tenho inclusive funções para montá-lo na estrutura correta do HTML baseado no perfil do usuário cadastrado, conforme suas permissões. Tudo isso fiz de forma recursiva, pois um menu pode apenas estar ligado diretamente a UM só pai, ou se não estiver ligado a nenhum ele é o topo. Com essa estrutura consegui chegar a multiplos níveis. O que preciso agora é apenas obter estes filhos para atender a uma forma que um component de grid trabalha e por isso eu preciso saber se é o ultimo nível ou não do menu. Da forma que fiz, só falta o hibernate parar de colocar a condição padrão que ele coloca, e deixar apenas a minha atuar.

Sinceramente, eu cheguei em outra ocasião, trabalhar da forma que me passou, mas tive problemas também com as montagens padrões que o hibernate fazia.

Enfim, eu também não sou um usuário avançado em Java, estou aprendendo, então com certeza foi algo errado que fiz…

Criado 30 de março de 2011
Ultima resposta 30 de mar. de 2011
Respostas 2
Participantes 2