Problema com retorno list de hql Hibernate

Boa noite, estou recebendo o seguinte erro em tempo de execução (ClassCastException)

Exception in thread “main” java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to pojo.ClientePojo

Alinha em que ocorre o erro é um system.out: >> System.out.println(lista.get(i).getNome());

Minha classe Pojo simplificada:

import enums.TipoCliente;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

/**
 *
 * @author SV EXPRESS
 */

@Entity
@Table(name = "clientes")
public class ClientePojo implements Serializable {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "ID")
    private long idCliente;
    
    @Column(name = "NOME_CLIENTE")
    private String nome;
    
    @Column(name = "SENHA")
    private String senha;
    
    @Enumerated(EnumType.STRING)
    @Column(name = "TIPO_CLIENTE")
    private TipoCliente tipoCliente;

 public long getIdCliente() {
        return idCliente;
    }

    /**
     * @return the nome
     */
    public String getNome() {
        return nome;
    }

    /**
     * @param nome the nome to set
     */
    public void setNome(String nome) {
        this.nome = nome;
    } 

    public TipoCliente getTipoCliente() {
        return tipoCliente;
    }

    /**
     * @param tipoCliente the tipoCliente to set
     */
    public void setTipoCliente(TipoCliente tipoCliente) {
        this.tipoCliente = tipoCliente;
    }


meu método na classe DAO:

public List procurarCliente(){
        
        Session session = HibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction();
        Query query = session.createQuery("select cp.nome, cp.tipoCliente from ClientePojo cp");
        List lista = query.getResultList();
        session.getTransaction().commit();
        HibernateUtil.closeSession();
        
        return lista;
    }

Onde chamo o método:

List<ClientePojo> lista = new ArrayList<>();
lista.addAll(cdao.procurarCliente(id));

for (int i = 0; i < lista.size(); i++) { 

      System.out.println(lista.get(i).getNome());
                            
 }

Minha dúvida: gostaria de saber o porque de ele tentar dar cast,e de que forma poderia resolver isso. Creio que poderia fazer com o uso de Generics mas não domino o assunto

obs: Consigo exibir o valor do List caso a hql que eu execute seja “from ClientePojo”, mas não acho legal fazer isso pois retorna todas as colunas do banco, e isso em grande escala não seria legal.

Vamos la

Generics foi introduzido no java 1.5 la em mil novecentos e guaraná com rolha.

Entretando List, ArrayList e outras Collections existem desde antes. Assim elas foram atualizadas para usar Generics porém existe uma retrocompatibilidade e, assim, vc pode fazer

List x = new ArrayList<>();

ou

List<Object> x = new ArrayList<>();

que serão equivalentes. Agora perceba que vc não tem nenhuma forma de estipular que tipo o metodo get vai retornar. Da forma como vc fez ele vai retorar um Object e todos as classes descendem de Object. Mas para vc chamar um metodo como getNome vc precisa fazer o cast.

como resolver? Simples!

List<ClientePojo> x = new ArrayList<>();

agora perceba que ainda vai existir um “cast” mas isso é feito dentro do ArrayList. Mas vc não pode armazenar outras coisas q nao sejam ClientePojo

`Boa tarde, no caso o resultado do hql é atribuido a um List local genérico dentro do método procurarCliente(), já quando o chamo, atribuo a um ArrayList(), então estou fazendo o cast, tentei também faze-lo dentro do método mas também não funcionou, mas por hora obrigado.

ah verdade nao percebi esse problema

tente assim

TypedQuery<ClientePojo> lQuery = myEntityManager.createQuery("from ClientePojo", ClientePojo.class);
List<ClientePojo> personList = lQuery.getResultList();

Percebi que vc utiliza Session, ao invés de Entity Manager, implemente o seguinte código para fazer o select:

public List<Cliente> procurarCliente(String nome) { // se vc quizer pode chamar o metodo colocando "" (aspas vazias para puxar pesquisa total)
        try {
            Criteria criteria = session.createCriteria(Cliente.class).addOrder(Order.asc("nomeCliente"));
            criteria.add(Restrictions.ilike("nomeCliente", nome, MatchMode.ANYWHERE));
            return criteria.list();
        } finally {
            session.close();
        }
    }

Este exemplo que montei, busca a partir da sua classe Cliente (que possui os GET e SETTERS identificados), e Ordena pelo nome do cliente de forma crescente.
Inclui também uma restrição que busca pelo nome do cliente, independente se é minusculo ou maiúsculo o nome. E caso vc n queira buscar pelo nome basta deixar chamar o metodo com a String “”(com aspas vazias).

Outra opção seria essa, que não tem todo aquele fru fru:

public List<Cliente> procurarCliente() { 
        try {
            return session.createCriteria(Cliente.class).list();
        } finally {
            session.close();
        }
}

Opa! Valeu, mas no caso, este exemplo retorna todas as colunas certo? com “from Cliente” em createQuery obtém-se o mesmo resultado, consigo imprimir, mas minha grande dúvida é em relaçao a exception que dá quando tento com select, de alguma forma, mesmo sem alterar a instancia de List, com um hql ele retorna Cliente e outro retorna Object, que no caso da ClassCastException pq internamente ele faz algo como “Cliente c = lista.get(i)” < exception, pois lista retorna Object quando usado select :frowning:

No meu exemplo ele retorna Cliente e não Object, o erro que possivelmente aparece pode estar relacionado ao f%*# Lazy que é causado por relacionamento de entidades desta classe, neste caso deve-se fazer um sub select, ou preencha um collection com os dados da outra tabela.

Obrigado a ajuda cara, acabei encontrando uma forma interessante de chegar ao resultado que eu esperava, retornando x colulas de Cliente, no caso uso o mesmo código hql com uma pequena alteração, fica o seguinte:

String strHqlSelect = “select new Cliente (c.nome, c.numConta) from Cliente c”;

Para que o mesmo funcione preciso criar um método construtor em Cliente passando como parâmetro os atributos que quero retornar.

Esse hql retorna uma Lista com instância de Cliente, logo consigo acessar sem problemas.

No mais, obrigado e fica também esse exemplo para acrescentar a vocês.