HIBERNATE - Selecionar campos retornados na consulta

Olá!

Tenho 3 tabelas:

Cliente: id_cliente, nome
Produto: id_produto, descricao, valor, qtd
Compra: id_compra, id_cliente, id_produto, qtd

Os campos id_cliente e id_produto na tabela Compra referenciam a tabela Cliente e Produto respectivamente.

Quero exibir uma página listando todas as compras, contendo o id_compra, nome do cliente, nome do produto e a quantidade.

Mapeamento do Cliente

@Entity
public class Cliente implements java.io.Serializable {
    
    //Chave primária    
    private Long id_cliente;  

    private String nome;

    private Set compras = new HashSet();
    
    /** Creates a new instance of Cliente */
    public Cliente() {
    }
    
    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getId_cliente() {
        return id_cliente;
    }

    public void setId_cliente(Long id_cliente) {
        this.id_cliente = id_cliente;
    }

    @NotNull
    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }
    
    @OneToMany(mappedBy="cliente")
    public Set<Compra> getCompras() {
        return compras;
    }

    public void setCompras(Set<Compra> compras) {
        this.compras = compras;
    }
}

Mapeamento do Produto:

@Entity
public class Produto implements java.io.Serializable {
    
    //Chave primária    
    private Long id_produto;  

    private String descricao;
    private float valor;
    private int qtd;    

    private Set compras = new HashSet();
    
    /** Creates a new instance of Produto */
    public Produto() {
    }

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getId_produto() {
        return id_produto;
    }

    public void setId_produto(Long id_produto) {
        this.id_produto = id_produto;
    }

    @NotNull
    public String getDescricao() {
        return descricao;
    }

    public void setDescricao(String descricao) {
        this.descricao = descricao;
    }

    @NotNull
    public float getValor() {
        return valor;
    }

    public void setValor(float valor) {
        this.valor = valor;
    }

    @NotNull
    public int getQtd() {
        return qtd;
    }

    public void setQtd(int qtd) {
        this.qtd = qtd;
    }   

    @OneToMany(mappedBy="produto")
    public Set<Compra> getCompras() {
        return compras;
    }

    public void setCompras(Set<Compra> compras) {
        this.compras = compras;
    }
}

Mapeamento da Compra

@Entity
public class Compra implements java.io.Serializable {
    
    //Chave primária
    private Long id_compra;   

    private int qtd;

    private Cliente cliente;
    private Produto produto;
    
    /** Creates a new instance of Compra */
    public Compra() {
    }

    @Id @GeneratedValue(strategy=GenerationType.IDENTITY)
    public Long getId_compra() {
        return id_compra;
    }

    public void setId_compra(Long id_compra) {
        this.id_compra = id_compra;
    }

    @ManyToOne(optional=false)    
    public Cliente getCliente() {
        return cliente;
    }

    public void setCliente(Cliente cliente) {
        this.cliente = cliente;
    }

    @ManyToOne(optional=false)    
    public Produto getProduto() {
        return produto;
    }

    public void setProduto(Produto produto) {
        this.produto = produto;
    }

    @NotNull
    public int getQtd() {
        return qtd;
    }

    public void setQtd(int qtd) {
        this.qtd = qtd;
    }    
}

Esta é a página.

<% BdCompra bdCompra = new BdCompra(); List compras = bdCompra.exibir(); if(compras!=null){ %> <table border="1"> <tr> <th>ID_COMPRA</th> <th>CLIENTE</th> <th>PRODUTO</th> <th>QUANTIDADE</th> </tr> <% for(int i=0; i<compras.size(); i++){ Compra compra = (Compra)compras.get(i); %> <tr> <td><%=compra.getId_compra()%></td> <td><%=compra.getCliente().getNome()%></td> <td><%=compra.getProduto().getDescricao()%></td> <td><%=compra.getQtd()%></td> </tr> <% } %> </table>

Função Exibir

public List exibir(){ try{ Session session = HibernateUtil.getSession(); return session.createQuery("from Compra").list(); }catch(Exception e){ return null; } }

Utilizando a função acima funcionou corretamente, porém todos os campos do cliente e produto são carregados. Eu gostaria de diminuir esta carga para que carregasse apenas os campos id_compra, nome do cliente, descricao do produto e a quantidade comprada.

Já tentei assim:

public List exibir(){ try{ Session session = HibernateUtil.getSession(); return session.createQuery( "select com.id_compra, com.qtd, com.cliente.nome, com.produto.descricao " + "from Compra com") .list(); }catch(Exception e){ return null; } }

Porém, o seguinte erro é retornado:

[code]
org.apache.jasper.JasperException: Exception in JSP: /etc.jsp:154

151: </tr>
152: <%
153: for(int i=0; i<compras.size(); i++){
154: Compra compra = (Compra)compras.get(i);
155: %>
156: <tr>
157: <td><%=compra.getId_compra()%></td>

Stacktrace:
org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:504)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:393)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:368)

root cause

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to modelo.Compra
org.apache.jsp.etc_jsp._jspService(etc_jsp.java:266)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:332)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:314)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:264)
javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:368[/code]

Alguém sabe como resolvo isso???

Desde já obrigado!

Opa,

Bom até onde eu sei o hibernate não faz carga parcial de objetos, ou seja, ele não carrega apenas 2 ou três propriedades de um bean… acredito que se for realmente necessário, você terá que popular isso aí na mão… Caso não tenha objetos do tipo text e sejam poucos campos você pode carregar o objeto todo.

Dica: Nem sempre é bom “recriar” seu modelo de dados em suas classes, relacionamentos e tal usando recursos do ORM.

:okok:

esta carga dos objetos nao é overhead algum. Mas se mesmo assim você preferir assim, de uma olhada em ResultTransformer do Hibernate.

Att.

Lindo vai ser quando ele iterar numa lista de compras heahaeheahae

Primeiramente, obrigado a todos pela ajuda :grin:

Desculpe a minha ignorância, mas porquê não é bom “recriar” meu modelo de classes e relacionamentos usando os recursos do ORM?

Valeu :grin:

[quote=“eloimendes”][quote=“marcossousa”]
Dica: Nem sempre é bom “recriar” seu modelo de dados em suas classes, relacionamentos e tal usando recursos do ORM.
[/quote]
porquê não é bom “recriar” meu modelo de classes e relacionamentos usando os recursos do ORM?
[/quote]

As vezes não é bom… quando tu precisa de mais performance, o que é difícil de se conseguir com um framework OR.

Usei o ResultTransformer da seguinte manteira:

public List exibir&#40;&#41;&#123; try&#123; Session session = HibernateUtil.getSession&#40;&#41;; //return session.createQuery&#40;&quot;from Compra&quot;&#41;.list&#40;&#41;; return session.createQuery&#40; &quot;select com.id_compra as id_compra, com.qtd as qtd, com.cliente.nome as nome, com.produto.descricao as descricao &quot; + &quot;from Compra com&quot;&#41; .setResultTransformer&#40;Transformers.aliasToBean&#40;Compra.class&#41;&#41; .list&#40;&#41;; &#125;catch&#40;Exception e&#41;&#123; return null; &#125; &#125;

Porém, ele retorna o seguinte erro:
“Could not find setter for nome on class modelo.Compra”

Isto quer dizer que eu tenho que criar uma outra classe com exatamente os campos que eu quero na consulta? :slight_smile:

O método não teria que interpretar que na classe Compra há um Cliente e nesse cliente há o atributo nome?