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

Em PedidoDAO preciso do seguinte:


    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(); // consulta do PedidoItemDAO
        	
            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;
            }
        }
    }

devido a eu precisar de uma lista dos itens do Pedido, montei a consulta citada acima.

Essa consulta me parece errada!

Se o método se chama findByPedido, você deveria passar o pedido como parâmetro para ele trazer os itens daquele pedido, como o @TerraSkilll já explicou lá em cima, pôxa, tem que prestar atenção no que os coleguinhas te passam no fórum.

Depois que você arrumar o método pra receber o pedido como parâmetro, provavelmente seu código vai ficar mais ou menos assim:

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);
    	
        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);

                final List<PedidoItem> itensPedido = pedidoItemDao.findByPedido(pedido); // consulta do PedidoItemDAO
                pedido.setItens(itensPedido);

                pedidos.add(pedido);
            }
            return pedidos;
        }
    }
}

sim, concordo, estou prestando bem atenção, porém como migrei do Delphi para o Java, muitas coisas ainda são confusas, e vou aprendendo no dia a dia… e oq realmente não estou conseguindo é fazer o método receber o pedido como parâmetro… mas irei tentar fazer as alterações.

Foi necessário passar o Pedido como parâmetro no Service e Controller;

E meu PedidoDAO fiz desta forma:

    public List<Pedido> findByIdCliente(Long idCliente, Pedido pedido) 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()
                	pedido.setId(rs.getLong("id"));
                	pedido.setPessoa(pessoa);
                    
                    final List<PedidoItem> itensPedido = pedidoItemDao.findByPedido(pedido); // consulta do PedidoItemDAO
                    		pedido.setItens(itensPedido);
                    		
                    pedidos.add(pedido);
                }
                return pedidos;
            }
        }
    }

porém tenho um retorno estranho,
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)

pesquisei sobre este erro, mas até o momento não consegui localizar o motivo.

Não acho que vc precisaria passar o Pedido como parâmetro da forma como vc fez. Se a ideia é recuperar todos os pedidos de um determinado cliente, apenas o ID do cliente é necessário.

Tentei refazer esse método de uma forma que faz mais sentido pra mim, de acordo com o que to entendendo do seu código:

public List<Pedido> findPedidosByIdCliente(Long idCliente) throws SQLException {
    try (
        PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?");
        ResultSet rs = psmt.executeQuery()
    ) {
        // Recupera o cliente pelo ID
        psmt.setLong(1, idCliente);
        Pessoa pessoa = pessoaDao.findById(idCliente);
        
        // Lista de pedidos do cliente
        List<Pedido> pedidos = new ArrayList<>();

        while (rs.next()) {
            Pedido pedido = new Pedido();
            pedido.setId(rs.getLong("id"));
            pedido.setPessoa(pessoa);

            // Recupera os itens do pedido
            List<PedidoItem> itensPedido = pedidoItemDao.findByPedido(pedido);
            pedido.setItens(itensPedido);
            
            pedidos.add(pedido);
        }
        
        return pedidos;
    }
}

Posta como que está o método findByPedido da classe PedidoItemDao pra gente ver.

opa, boa noite!

    public List<PedidoItem> findByPedido(Pedido pedido) throws SQLException {
        List<PedidoItem> itensPedido = new ArrayList<>();
        ProdutoDAO produtoDao = new ProdutoDAO(getConnection());

        PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedidoItem WHERE 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("idProduto"))) // usa o dao de produto pra buscar o produto pelo idProduto da tabela PedidoItem
                        .setQuantidade(rs.getInt("qntd"))
                        .setPedido(pedido); // usa o pedido

                itensPedido.add(item);
            }
        }

        return itensPedido;
    }

qndo eu estava testando sem parâmetros:

PedidoItemDAO:

    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(pedido);                           
                    itensPedido.add(item);
                }
                return itensPedido;
            }
        }
    }

PedidoDAO:

    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;
            }
        }
    }

E do jeito que tá agora, tah funcionando?

é que no caso, como o colega explicou acima, em PedidoItemDAO, eu tenho uma consulta por pedido e teria que ficar assim:

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;
}

porém eu nao estou sabendo instanciar o pedido, para receber a ID e setar ela como parâmetro na query :confused:

Mas vc já está fazendo isso aqui. Nessa parte vc recupera os pedidos do banco e cria o Pedido com o ID setado. Depois disso, só chamar o método que recupera os itens. Não é isso?

posso estar me perdendo em alguma parte… vou analisar melhor e tentar implementar

Tentei desta forma:

PedidoDAO:


	public List<Pedido> findPedidosByIdCliente(Long idCliente) throws SQLException {
		try (PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedido WHERE idCliente = ?")) {
			// Recupera o cliente pelo ID
			psmt.setLong(1, idCliente);
			
			try (ResultSet rs = psmt.executeQuery()) {
				Pessoa pessoa = pessoaDao.findById(idCliente);

				// Lista de pedidos do cliente
				List<Pedido> pedidos = new ArrayList<>();

				while (rs.next()) {
					Pedido pedido = new Pedido();
					pedido.setId(rs.getLong("id"));
					pedido.setPessoa(pessoa);

					// Recupera os itens do pedido
					List<PedidoItem> itensPedido = pedidoItemDao.findByPedido(pedido);
					pedido.setItens(itensPedido);

					pedidos.add(pedido);
				}

				return pedidos;
			}
		}
	}

PedidoItemDAO:

    public List<PedidoItem> findByPedido(Pedido pedido) throws SQLException {
        List<PedidoItem> itensPedido = new ArrayList<>();
        ProdutoDAO produtoDao = new ProdutoDAO(getConnection());

        PreparedStatement psmt = getConnection().prepareStatement("SELECT * FROM pedidoItem WHERE 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("idProduto")))
                        .setQuantidade(rs.getInt("qntd"))
                        .setPedido(pedido); // usa o pedido

                itensPedido.add(item);
            }
        }

        return itensPedido;
    }

porém me retorna:

at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:774)
Cannot render error page for request [/pedidos/listar/1] as the response has already been committed. As a result, the response may have the wrong status code.

É só fazer como eu postei lá em cima:

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);
    	
        try (ResultSet rs = psmt.executeQuery()) {
            final List<Pedido> pedidos = new ArrayList<>();
            while (rs.next()) {
                // instanciando o pedido
                final Pedido pedido = new Pedido()
                        .setId(rs.getLong("id"))
                        .setPessoa(pessoa);

                // carregando os itens do pedido
                final List<PedidoItem> itensPedido = pedidoItemDao.findByPedido(pedido); // consulta do PedidoItemDAO

                // setando os itens no pedido
                pedido.setItens(itensPedido);

                // adicionando o pedido na lista
                pedidos.add(pedido);
            }
            return pedidos;
        }
    }
}

Tá, mas esse erro aí não é nas suas consultas, em que momento que acontece esse erro?

esse retorno é quando bate no endpoint para listar por cliente. estou trabalhando só no backend e testando via localhost:8080…

Pode ser erro de referência circular, pois há um Pedido no PedidoItem e uma lista de PedidoItem no Pedido. Com isso, ao serializar pra json, dá problema. Faça um teste deixando o Pedido de cada PedidoItem como null e veja o que acontece.

1 curtida

limpei a tabela PedidoItem, e realmente, o erro não ocorreu.

Repare que não é deixar null no banco, mas sim na hora de criar as instâncias no código da aplicação.

dsclp o engano…

alterei para:
pedido.setItens(null);

e o erro não ocorreu tbm;

Saudações meu querido!

Você precisa abrir o Objeto PEDIDO antes ou depois de iniciar o WHILE, se nao vc estará abrindo um novo objeto pedido enquanto estiver rodando o WHILE.

Dentro do while, armazene os dados recebidos do banco em variáveis declaradas anteriormente.

Depois insira as variáveis no Objeto PEDIDO.

1 curtida