Problema com mapeamento Hibernate [Resolvido]

7 respostas
eduardoazevedo3

Olá pessoal,

estou com um problema no hibernate!

Tenho as classes Aluno e Notas; (Só coloquei os campos que estou tendo problema)

public class Aluno implements Serializable { ... @OneToMany(mappedBy = "aluno") private List<Nota> nota; ... }

public class Nota implements Serializable { ... @OneToOne(cascade = CascadeType.ALL) private Aluno aluno; ... }

As tabelas criaram certinho, do jeito que eu queria, mas quando eu tento executar um JOIN no HQL, dá pau…

HQL ==>>

public List<Aluno> filtrar(String valor) throws Exception{ String hql = "FROM Aluno aluno " + "INNER JOIN aluno.nota AS nota " + "WHERE nomealuno LIKE '%" + valor + "%'"; return (List<Aluno>) session.createQuery(hql).list(); }

Com este comando o hibernante gera o SELECT certo mas não conseguem preencher a classe Aluno…

Se eu tirar o JOIN ai dá certo…

Dá este erro:

SEVERE: null java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to model.dto.Aluno

Alguem sabe porque isso?

7 Respostas

paulo1911

olá eduardoazevedo3,

Na verdade no Hibernate pelo manos, quando vc usa hql com inner join a consulta vai te retornar uma lista de Object…
Que na verdade para cada elemento da lista de object, vc vai ter que fazer um cast para um array…onde cada indice do array é um campo da consulta que vc fez…

Se vc retitrar o join funciona pq a hql não fazendo join ela identifica que é um select de um unico tipo de objeto…onde com join…são outros tipos de objeto…OK!

Acredito que seja isso.

Fallow

renanreismartins

amigo vc precisa mesmo de um relacionamento bi-direcional, ou seja, a nota precisa conhecer seu aluno ? acho isso desncessario. Mas se realmente for, anote o campo aluno com a anotaçao @ManyToOne.

entao vc faz uma busca por aluno normalmente, algo como

String hql = "SELECT a FROM Aluno a WHERE a.nome LIKE :nome"

evite concatenar strings, use namedParameters ou criteria.

depois vc consegue pegar as notas do aluno apenas chamando o atributo notas

aluno.getNotas();

grande abrasssss

Hebert_Coelho

Concordo com ele.

Notas só tem um aluno, ou seja, @ManyToOne, mas defendo que a nota não precisa conhecer o aluno. [=

eduardoazevedo3

Certo, realmente, neste caso a Nota não precisa conhecer o Aluno, é que este foi só um exemplo para ilustrar um problema, na verdade tenho uma classe com vários relacionamentos eu só usei este para resumir…

Este esquema de fazer assim:

aluno.getNotas()

Deu certo, mas não era isso que eu queria, aquele HQL teria que fazer o preenchimento da classe Aluno com as respectivas Notas…

Pois se eu executar um “for” percorrendo 1000 alunos dando um getNotas() ele vai executar 1000 comando SQL buscando por notas do aluno, agora imagina este sistema na WEb com 10 pessoas trabalhando na mesma tela ao mesmo tempo, a performance vai lá em baixo…

Tipo se eu fizer assim:

public List<Aluno> filtrar() throws Exception{
        return (List<Aluno>) session.createCriteria(Aluno.class).list();
}

Utilizando criteria dá certinho do jeito que eu quero, preenche a classe Aluno com as notas dele…

Agora porque com o HQL não dá certo?

Eu olhei o SQL gerado tanto com HQL quanto com Criteria, e o SQL é extamente igual, só que quando uso HQL ele dá aquele ERRO…

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to model.dto.Aluno

Só lembrando, no meu caso tem que ser utilizando HQL… Criteria não serve…

eduardoazevedo3

Olá Pessoal,

Fiz um jeito aqui que deu certo, ficou assim:

public List<Aluno> filtrar() throws Exception{
        String hql = "FROM Aluno aluno " +
                     "LEFT JOIN aluno.nota";

        List<Object[]> listaObjs = session.createQuery(hql).list();

        List<Aluno> listaAluno = new ArrayList<Aluno>();

        for (int i = 0; i < listaObjs.size(); i++) {
            Object[] object = listaObjs.get(i);
            Aluno aluno = (Aluno) object[0];
            aluno.setNota((Nota) object[1]);
            listaAluno .add(aluno);
        }
        return listaAluno;
    }

Ao inves de Hibernate retornar a classe Aluno com a listaNotas preenchido, ele retornou uma list<Object> e dentro desta lista cada Objeto tem duas posicoes, uma com a classe Aluno preenchida e outra com uma list<Notas> preenchida…

Agora eu imagino num relacionamento com 10 tabelas, vai ficar horrivel…

não tem como fazer de um jeito melhor não?

eduardoazevedo3

Consegui..

Vlw galera...

ficou assim:

public List&lt;Aluno&gt; filtrar() throws Exception{
        String hql = "FROM Aluno aluno " +
                           "LEFT JOIN FETCH aluno.nota";

        return session.createQuery(hql).list();
    }

Estava só faltando o comando: FETCH

almircampos
eduardoazevedo3:
Consegui..

Vlw galera...

ficou assim:

public List&lt;Aluno&gt; filtrar() throws Exception{
        String hql = "FROM Aluno aluno " +
                           "LEFT JOIN FETCH aluno.nota";

        return session.createQuery(hql).list();
    }

Estava só faltando o comando: FETCH

Cara, ajudou bastante. Obrigado!

Criado 15 de dezembro de 2010
Ultima resposta 19 de ago. de 2012
Respostas 7
Participantes 5