2
respostas

[Dúvida] JOIN FETCH e items do pedido

Ola,

Quando consultamos por um pedido usando join fetch com cliente, os items estao disponiveis no resultado da querie, porque? Seria por causa do JPA perceber o relacionamento de um pedido contem varios itens, e o pedido ser o pk da relacao e ele estar sendo carregado... Ou nao tem relacao ?

Fiquei com essa duvida, como os items do pedido retornaram ali.

SELECT JOIN FETCH

Hibernate: 
    select
        pedido0_.id as id1_3_0_,
        cliente1_.id as id1_1_1_,
        pedido0_.cliente_id as cliente_4_3_0_,
        pedido0_.data_cadastro as data_cad2_3_0_,
        pedido0_.valor_total as valor_to3_3_0_,
        cliente1_.cpf as cpf2_1_1_,
        cliente1_.nome as nome3_1_1_ 
    from
        pedidos pedido0_ 
    inner join
        clientes cliente1_ 
            on pedido0_.cliente_id=cliente1_.id 
    where
        pedido0_.id=?
Pedido{id=1, dataCadastro=2023-04-25, valorTotal=22500.00, cliente=Cliente{id=1, nome='Eduardo', cpf='12345678901'}, itens=[ItemPedido{quantidade=10precoUnitario=1500.00}, ItemPedido{quantidade=5precoUnitario=1500.00}]}

Pedido

package br.com.alura.loja.modelo;

import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;

@Entity
@Table(name="pedidos")
public class Pedido {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name="data_cadastro")
    private LocalDate dataCadastro = LocalDate.now();


    @Column(name="valor_total")
    private BigDecimal valorTotal = BigDecimal.ZERO;

    @ManyToOne(fetch = FetchType.LAZY)
    private Cliente cliente;

    @OneToMany(mappedBy="pedido", cascade = CascadeType.ALL)
    private List<ItemPedido> itens = new ArrayList<ItemPedido>();

    public Pedido() {}

    public Pedido(Cliente cliente) {
        this.cliente = cliente;
    }

    public void adicionarItem(ItemPedido itemPedido) {
        itemPedido.setPedido(this);
        BigDecimal valorTotalDeItems = itemPedido.getPrecoTotal();
        this.valorTotal = this.valorTotal.add(valorTotalDeItems);
        this.itens.add(itemPedido);
    }


    @Override
    public String toString() {
        return "Pedido{" +
                "id=" + id +
                ", dataCadastro=" + dataCadastro +
                ", valorTotal=" + valorTotal +
                ", cliente=" + cliente +
                ", itens=" + itens +
                '}';
    }

    public Collection<Object> getItems() {
        return Collections.unmodifiableCollection(this.itens);
    }

    public String getCliente() {
        return this.cliente.toString();
    }
}

ItemPedido

package br.com.alura.loja.modelo;

import javax.persistence.*;
import java.math.BigDecimal;

@Entity
@Table(name="itens_pedido")
public class ItemPedido {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "preco_unitario")
    private BigDecimal precoUnitario;

    private int quantidade;

    @ManyToOne(fetch = FetchType.LAZY)
    private Pedido pedido;

    @ManyToOne(fetch = FetchType.LAZY)
    private Produto produto;

    public ItemPedido() {}

    public ItemPedido(int quantidade, Produto produto, Pedido pedido) {
        this.quantidade = quantidade;
        this.produto = produto;
        this.precoUnitario = produto.getPreco();
        this.pedido = pedido;
    }

    public void setPedido(Pedido pedido) {
        this.pedido = pedido;
    }

    public BigDecimal getPrecoTotal() {
        return new BigDecimal(this.quantidade).multiply(this.precoUnitario);
    }

    @Override
    public String toString() {
        return "ItemPedido{" +
                "quantidade=" + quantidade +
                "precoUnitario=" + precoUnitario +
                '}';
    }
}
2 respostas

Oi Eduardo!

O código não era para executar e sim dar uma exception LazyInitializationException ao tentar acessar a lista de itens do pedido.

Manda aqui o código da sua classe main

Aqui

package br.com.alura.loja.testes;

import br.com.alura.loja.dao.CategoriaDAO;
import br.com.alura.loja.dao.ClienteDAO;
import br.com.alura.loja.dao.PedidoDAO;
import br.com.alura.loja.dao.ProdutoDAO;
import br.com.alura.loja.enumerations.CategoriaPreco;
import br.com.alura.loja.modelo.*;
import br.com.alura.loja.util.JpaUtil;
import br.com.alura.loja.vo.RelatorioDeVendasVO;

import javax.persistence.EntityManager;
import java.math.BigDecimal;
import java.util.List;

public class CadastroDePedido {

    public static void main(String[] args) {
        popularBancoDeDados();
        EntityManager em = JpaUtil.getEntityManagerInstance();
        ClienteDAO clienteDAO = new ClienteDAO(em);
        ProdutoDAO produtoDAO = new ProdutoDAO(em);
        PedidoDAO pedidoDAO = new PedidoDAO(em);

        Cliente cliente = clienteDAO.buscarPorId(1L);
        Produto produto1 = produtoDAO.buscarPorId(1L);
        Produto produto2 = produtoDAO.buscarPorId(2L);
        Produto produto3 = produtoDAO.buscarPorId(3L);

        em.getTransaction().begin();

        Pedido pedido = new Pedido(cliente);
        pedido.adicionarItem(new ItemPedido(10, produto1, pedido));
        pedido.adicionarItem(new ItemPedido(5, produto2, pedido));

        pedidoDAO.cadastrar(pedido);

        Pedido pedido2 = new Pedido(cliente);
        pedido2.adicionarItem(new ItemPedido(5, produto2, pedido2));
        pedido2.adicionarItem(new ItemPedido(10, produto3, pedido2));

        pedidoDAO.cadastrar(pedido2);

        em.getTransaction().commit();

        BigDecimal valorTotal = pedidoDAO.valorTotalVendido();
        System.out.println("Valor Total: " + valorTotal);

        List<RelatorioDeVendasVO> relatorioDeVendas = pedidoDAO.relatorioDeVendas();
        relatorioDeVendas.forEach(System.out::println);

        Pedido pedidoRealizado = em.find(Pedido.class, 1L);
        System.out.println(pedidoRealizado.getItems().size());
        System.out.println(pedidoRealizado.getCliente());

        Pedido pedidoComCliente = pedidoDAO.buscarPedidoComCliente(1L);
        System.out.println(pedidoComCliente);

        em.close();
    }

    private static void popularBancoDeDados() {
        EntityManager em = JpaUtil.getEntityManagerInstance();

        Categoria categoria = new Categoria(
                "Celulares"
        );
        Categoria categoria2 = new Categoria(
                "Videogames"
        );
        Categoria categoria3 = new Categoria(
                "Computadores"
        );


        Produto celular = new Produto(
                "Xiaomi Redmi",
                "Celular top",
                new BigDecimal("1500.00"),
                CategoriaPreco.PRECO_MEDIO,
                categoria
        );
        Produto videogame = new Produto(
                "PS5",
                "Videogame top",
                new BigDecimal("1500.00"),
                CategoriaPreco.PRECO_MEDIO,
                categoria2
        );
        Produto computador = new Produto(
                "Macbook",
                "Computador top",
                new BigDecimal("1500.00"),
                CategoriaPreco.PRECO_MEDIO,
                categoria3
        );


        Cliente cliente = new Cliente(
                "Eduardo",
                "12345678901"
        );

        em.getTransaction().begin();
        CategoriaDAO categoriaDAO = new CategoriaDAO(em);
        ProdutoDAO produtoDAO = new ProdutoDAO(em);
        ClienteDAO clienteDAO = new ClienteDAO(em);

        categoriaDAO.cadastrar(categoria);
        categoriaDAO.cadastrar(categoria2);
        categoriaDAO.cadastrar(categoria3);
        produtoDAO.cadastrar(celular);
        produtoDAO.cadastrar(videogame);
        produtoDAO.cadastrar(computador);

        clienteDAO.cadastrar(cliente);

        em.getTransaction().commit();
        em.close();

    }

}

A consulta do PedidoDAO

    public Pedido buscarPedidoComCliente(long id) {
        return em.createQuery("SELECT p FROM Pedido p " +
                        "JOIN FETCH p.cliente " +
                        "WHERE p.id=:id", Pedido.class)
                .setParameter("id", id)
                .getSingleResult();
    }

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software