Qual seria a forma correta de percorrer a lista e retornar os dados?

boa tarde. por estar iniciando, não consegui compreender como irei setar a “Pessoa” e retornar ela na lista “Pedido” …

    public List<Pedido> findById(Long idCliente) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
        	psmt.setLong(1, idCliente); // parâmetro da query
        	
        	Pessoa pessoa = new Pessoa();
        	pessoa.setId(1);
        	
            try (ResultSet rs = psmt.executeQuery()) {
                final List<Pedido> pedidos = new ArrayList<>();
                while (rs.next()) {
                    final Pedido pedido = new Pedido()
                            .setId(rs.getLong("id"))
                            .setPessoa(pessoa);
                    pedidos.add(pedido);
                }
                return pedidos;
            }
        }
    }

desta forma não esta retornando os dados da Pessoa.

Da mesma forma que você tem esse findById() para busca os dados do pedido, eu imagino que você tenha um método pra chamar o cliente, certo? Seria o caso de usá-lo da mesma forma:

public List<Pedido> findById(Long idCliente) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
        	psmt.setLong(1, idCliente); // parâmetro da query

        	Pessoa pessoa = ClienteRepository.findById(idCliente); // retorna o cliente pelo id

ou mesmo passar o cliente já preenchido para esse método que busca os pedidos. Algo como:

// O parâmetro é alterado para uma instância de Pessoa/Cliente
public List<Pedido> findById(Pessoa pessoa) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
        	psmt.setLong(1, pessoa.getId()); // parâmetro da query

              // o Pessoa pessoa = new Pessoa(); é totalmente removido, já que já está preenchido.

Abraço.

Obrigado pela resposta;

Neste exemplo em questão, não utilizo Repository, é utilizado DAO.

E no caso, eu tenho a entidade Pedido e Pessoa.

Na classe pedido, tenho minha classe pessoa desta forma: private Pessoa pessoa;

ao retornar a lista, teria que entender que tal pedido seria de tal pessoa… não sei se consegui ser mt claro.

Então você vai ter que primeiro fazer um select na tabela de Pessoa para encontrar a pessoa com o mesmo id do idPessoa no pedido.
Depois seta a pessoa encontrada no objeto Pedido que você está montando.

montei a query em PessoaDAO:

    public Pessoa findById(Long id) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pessoa WHERE id = ?")) {
            try (ResultSet rs = psmt.executeQuery()) {
            	psmt.setLong(1, id); // parâmetro da query
            	
                   Pessoa pessoa = new Pessoa()
                            .setId(rs.getLong("id"))
                            .setNome(rs.getString("nome"))
                            .setCpf(rs.getString("cpf"));
                   
                
                return pessoa;
            }
        }
    }

porém não estou sabendo como implementar corretamente na classe PedidoDAO, para montar a lista :confused:

Pessoa pessoa = pessoaDao.findById(idCliente);

fiz desta forma,

PedidoDAO:

public class PedidoDAO extends DAO {
	
	PessoaDAO pessoaDao;

    public PedidoDAO(final Connection connection) {
        super(connection);
    }
    
    public List<Pedido> findById(Long idCliente) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
        	psmt.setLong(1, idCliente); // parâmetro da query
        	
        	Pessoa pessoa = pessoaDao.findById(idCliente);
        	
            try (ResultSet rs = psmt.executeQuery()) {
                final List<Pedido> pedidos = new ArrayList<>();
                while (rs.next()) {
                    final Pedido pedido = new Pedido()
                            .setId(rs.getLong("id"))
                            .setPessoa(pessoa);
                            //.setItens(pedidosItem);
                    pedidos.add(pedido);
                }
                return pedidos;
            }
        }
    }
}

PessoaDAO:

public class PessoaDAO extends DAO {

    public PessoaDAO(final Connection connection) {
        super(connection);
    }

    
    public Pessoa findById(Long id) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pessoa WHERE id = ?")) {
            try (ResultSet rs = psmt.executeQuery()) {
            	psmt.setLong(1, id); // parâmetro da query
            	
                final Pessoa pessoa = new Pessoa()
                            .setId(rs.getLong("id"))
                            .setNome(rs.getString("nome"))
                            .setCpf(rs.getString("cpf"));
                
                return pessoa;
            }
        }
    }
}

porém me retorna o erro:
Cannot invoke "br.com.desafio.desafio.dao.PessoaDAO.findById(java.lang.Long)" because "this.pessoaDao" is null

A mensagem está bem clara, você não inicializou o atributo pessoaDao.

entendo… é que no caso tentei:
PessoaDAO pessoaDao = new PessoaDAO();

porém como a classe pede os argumentos de conexão, não sei como seria a forma correta de implementar… comecei a mexer agora com este padrão DAO, e ainda estou um pouco confuso :confused:

Como é que você instância o PedidoDao?
Vai ser da mesma forma.

sim, pensei desta forma tbm…

    public PedidoDAO(final Connection connection) {
        super(connection);
    }
    
    public PessoaDAO(final Connection connection) {
        super(connection);
    }

Porém no PessoaDAO, me gerou: “Constructor call must be the first statement in a constructor” … estou pesquisando mas não encontro o motivo

Pôxa, você está tentando declarar o construtor da classe PessoaDAO dentro da classe PedidoDAO.

Seu PedidoDAO vai ter um atributo do tipo PessoaDAO.

No construtor você inicializa o atributo.

class PedidoDAO {

    private final PessoaDAO pessoaDao;

    public PedidoDAO(final Connection connection) {
        super(connection);
        this.pessoaDao = new PessoaDAO(connection);
    }
}
1 curtida

que mancada, não me atentei nisso… vou fazer os testes assim que possível.

1 curtida

bom dia!

gostaria de agradecer sua ajuda!! consegui retornar a lista de clientes deste pedido.

porém agora preciso retornar uma lista com os itens deste pedido. Pelo que entendi, terei que retornar uma lista de PedidoItem, exemplo:

SELECT * FROM pedidoItem WHERE idPedido = ?

em PedidoItem estão as classes:

 private Produto produto;
 private Pedido pedido;

porém não vejo uma forma de fazer isto pois são parâmetros diferentes, e é enviado apenas 1 na URL.

Em PedidoItemDAO fiz o seguinte:

    public List<PedidoItem> findByPedido() throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedidoItem pe LEFT JOIN pedido p ON pe.id = p.id")) {
            try (ResultSet rs = psmt.executeQuery()) {
                final List<PedidoItem> itensPedido = new ArrayList<>();
                while (rs.next()) {
                    final PedidoItem item = new PedidoItem()
                            .setId(rs.getLong("id"))
                            //.setProduto(null)
                            .setQuantidade(rs.getInt("qntd"));
                            //.setPedido(null);                           
                    itensPedido.add(item);
                }
                return itensPedido;
            }
        }
    }

aparentemente esta retornando correto, oq resta é setar o Produto e Pedido de acordo

Se a tabela de PedidoItem tem uma coluna para o id do pedido, você não precisa desse left join, pode fazer o select direto na tabela de pedidoItem. Também está faltando um parâmetro para definir de qual pedido você quer carregar. Da forma como está, está carregando todos os itens de todos os pedidos.

Se a ideia desse método é carregar os itens de um pedido que você já tem carregado, eu somente passaria a instância dele para o método, em vez de ter o trabalho de carregar de novo. E, para os dados do produto, você precisa de um DAO pra carregá-lo, da mesma forma que já vem fazendo. Algo como:

public List<PedidoItem> findByPedido(Pedido pedido) throws SQLException {
    List<PedidoItem> itensPedido = new ArrayList<>();
    ProdutoDAO produtoDao = new ProdutoDAO(getConnection()); // dao de consulta a produtos, similar aos demais

    PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedidoItem pe WHERE pe.id = ?");
    psmt.setLong(1, pedido.getId());
    try (ResultSet rs = psmt.executeQuery()) {
        while (rs.next()) {
            final PedidoItem item = new PedidoItem()
                    .setId(rs.getLong("id"))
                    .setProduto(produtoDao.findById(rs.getLong("id_produto"))) // usa o dao de produto pra buscar o produto pelo id_produto da tabela pedido_item
                    .setQuantidade(rs.getInt("qntd"));
                    .setPedido(pedido); // usa o pedido

            itensPedido.add(item);
        }
    }

    return itensPedido;
}

Abraço.

1 curtida

muito obrigado!

acho que consegui compreender oq disse… porém não estou sabendo ao certo, como vou instanciar o Pedido corretamente :confused:

no caso, esta lista que fiz, é para retornar todos os itens do pedido, pois nesta consulta tenho o idProduto… e a cada vez que passar no while, cria um novo produto, para setar ele na lista.


    public List<PedidoItem> findByPedido() throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedidoItem pi LEFT JOIN pedido p ON pi.id = p.id")) {
            try (ResultSet rs = psmt.executeQuery()) {
                final List<PedidoItem> itensPedido = new ArrayList<>();
                while (rs.next()) {
                	Produto produto = produtoDao.findById(rs.getLong("idProduto"));

                    final PedidoItem item = new PedidoItem()
                            .setId(rs.getLong("id"))
                            .setProduto(produto)
                            .setQuantidade(rs.getInt("qntd"));
                            //.setPedido(null);                           
                    itensPedido.add(item);
                }
                return itensPedido;
            }
        }
    }

Não é o seu PedidoDAO quem carrega os pedidos do banco?
É só você usar seu PesidoDAO para obter o pedido e passar ele como parâmetro como o @TerraSkilll ensinou.

Em PedidoDAO, carrego uma lista com todos os pedidos e todos os pedidos por idCliente, terei que criar um que retorne somente o pedido específico?

PedidoDAO até o momento:

    public List<Pedido> findAll() throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido")) {
            try (ResultSet rs = psmt.executeQuery()) {
                final List<Pedido> pedidos = new ArrayList<>();
                while (rs.next()) {
                    final Pedido pedido = new Pedido()
                            .setId(rs.getLong("id"));
                    pedidos.add(pedido);
                }
                return pedidos;
            }
        }
    }
    
    public List<Pedido> findByIdCliente(Long idCliente) throws SQLException {
        try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
        	psmt.clearParameters();
        	psmt.setLong(1, idCliente); // parâmetro da query
        	
        	Pessoa pessoa = pessoaDao.findById(idCliente);
        	List<PedidoItem> itensPedido = pedidoItemDao.findByPedido();
        	
            try (ResultSet rs = psmt.executeQuery()) {
                final List<Pedido> pedidos = new ArrayList<>();
                while (rs.next()) {
                    final Pedido pedido = new Pedido()
                            .setId(rs.getLong("id"))
                            .setPessoa(pessoa)
                            .setItens(itensPedido);
                    pedidos.add(pedido);
                }
                return pedidos;
            }
        }
    }