Eu não entendi como precisa ser feito via Hibernate o mapeamento que descrevo abaixo.
Existe uma tabela chamada TAB_CATEGORIA que represente, como o nome diz, uma categoria.
Uma categoria pode ter 0 ou mais categorias filhas dela. Este relacionamento de pertinência é dado pelo campo idPai.
Ou seja, para ver todas categorias filhas de uma categoria eu preciso fazer um SQL
O Problema é que não sei como fazer este mapeamento no Hibernate através de anotações.
Eu tentei fazer como mostrado em meu código abaixo, mas não estou tendo sucesso. Podem me ajudar?
@NamedQueries( {
@NamedQuery(name = "Categoria.obterListaCategoria",
query = "FROM Categoria C " +
"ORDER BY C.nome"),
@NamedQuery(name = "Categoria.obterListaRootCategoria",
query = "FROM Categoria C " +
"WHERE (C.idPai = -1) " +
"ORDER BY C.nome"),
@NamedQuery(name = "Categoria.obterCategoriasFilho",
query = "FROM Categoria C " +
"WHERE (C.idPai = :IdPaiCategoria) " +
"ORDER BY C.nome") })
@Entity
@Table(name = "TAB_CATEGORIA")
@SequenceGenerator(name = "CATEGORIA_SEQ", sequenceName = "CATEGORIA_SEQ")
/**
* Forma de organizar hierarquicamente um produto.
* Uma categoria pode ter uma ou mais sub categorias.
* Uma categoria pode ter uma ou nenhuma categoria pai.
*/
public class Categoria implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "CATEGORIA_SEQ")
@Column(name = "ID_CATEGORIA")
private int id;
@Column(name = "NM_CATEGORIA")
private String nome;
@JoinColumn(name = "ID_CATEGORIA",referencedColumnName="IDPAI_CATEGORIA")
@Column(name = "IDPAI_CATEGORIA")
private int idPai;
@OneToMany(cascade = CascadeType.REFRESH, fetch = FetchType.LAZY )
@JoinTable(name="Categoria")
private List<Categoria> filhos;
public List<Categoria> getFilhos() {
return filhos;
}
public void setFilhos(List<Categoria> filhos) {
this.filhos = filhos;
}
public static List<Categoria> obterListaCategoria() {
Session session = HibernateUtil.getSessionFactory().openSession();
org.hibernate.Query q = session
.getNamedQuery("Categoria.obterListaCategoria");
List<Categoria> resultado = q.list();
session.close();
return resultado;
}
public static List<Categoria> obterListaRootCategoria() {
return obterCategoriasFilho(-1);
}
public int getId() {
return this.id;
}
public int getIdPai() {
return idPai;
}
public String getNome() {
return this.nome;
}
public void setId(int id) {
this.id = id;
}
public void setIdPai(int idPai) {
this.idPai = idPai;
}
public void setNome(String nome) {
this.nome = nome;
}
public String toString(){
StringBuilder builder = new StringBuilder();
builder.append("{id=").append(this.id).append(" ,nome=").append(this.nome).append(" ,pai=").append(this.idPai).append("}");
return builder.toString();
}
}
Desculpe, mas acho que não fui claro na dúvida.
O Problema é que a entidade tem um relacionamento de 1 para n com ela mesma.
Na classe existe o Javadoc que mostra exatamente o relacionamento.
[code]/**
Forma de organizar hierarquicamente um produto.
Uma categoria pode ter uma ou mais sub categorias.
Uma categoria pode ter uma ou nenhuma categoria pai.
*/ [/code]
Por sub categoria entenda-se um outro elemento da mesma classe chamada categoria. Idêntico como objeto e mapeado para a mesma tabela.
O relacionamento está entre o id e o idPai.
o idPai é o id da categoria pai.
Exemplo:
Categoria 1: id=1, nome=Teste 0, idPai=-1
Categoria 2: id=2, nome=Filha de Teste 1, idPai=1
Categoria 3: id=3, nome=Filha de Teste 2, idPai=1
Quando eu executar o método getFilhos da instância da classe Categoria que armazena Categoria 1 ele deverá me retornar uma List formada pela Categoria 2 e Categoria 3.
A Query SQL que deveria fazer isso é:
Entendeu?
A dúvida é como mapear/anotar o metodo getFilhos e os campos pertinentes na classe Categoria.
Uma alternativa, caso não seja possível fazer esse relacionamento sem uma tabela auxiliar, seria usar uma tabela extra chamada TAB_CATEGORIA_TAB_CATEGORA que teria apenas o idPai e idFilho.
TAB_CATEGORIA_TAB_CATEGORA.idPai haveria um relacionamento com TAB_CATEGORIA.id
TAB_CATEGORIA_TAB_CATEGORA.idFilho haveria um relacionamento com TAB_CATEGORIA.id
E ai a amarração seria feita.
Seria o equivalente a, em SQL, usar a seguinte query para obter os dados desejados:
SELECT
C.id,
C.nome
FROM
TAB_CATEGORIA C,
TAB_CATEGORIA_TAB_CATEGORIA XC
WHERE
C.id = XC.idPai AND
XC.idPai = ?
Usando esta abordagem, como ficaria o mapeamento em anotações da classe Categoria?