1
resposta

Dúvida sobre o método buscarPedidoComCliente

Eu fiz o código como descrito na aula, porém eu sempre vinha com uma dessas exceções:

Exception in thread "main" javax.persistence.NonUniqueResultException: query did not return a unique result: 5

ou então

Exception in thread "main" javax.persistence.NoResultException: No entity found for query

Na linha de acordo com a aula a parte do "where p.id = :id" , estava comparando o id do PEDIDO com o id do CLIENTE passado como parâmetro, e desse modo como eu não tinha um pedido de ID 1, eu peguei a segunda exceção. O problema é que eu vejo é que pra funcionar, necessariamente haveria de ter um cliente com id igual ao do pedido. Se eu tivesse um pedido com ID = 1, semelhante a um ID = 1 passado como parâmetro, o código iria funcionar de boas, mas ainda sim é estranho porque um cliente pode efetuar vários pedidos diferentes, ou seja, mantendo o seu ID e portanto tendo seu ID diferente do ID dos pedidos, o que com certeza irá quebrar o código como aconteceu com o meu.

A segunda exceção surgiu quando tentei mudar pra resolver esse problema e coloquei "where p.cliente.id = :id", porque aí sim, ele iria comparar o id do cliente do pedido com o id do cliente passado na busca. Porém, no meu BD, há 5 pedidos diferentes feitos por uma mesma cliente de ID = 1. A primeira exceção aconteceu pois ao buscar pelo pedido através do cliente na tabela de pedidos, ele retornou 5 resultados iguais já que eu procurava pelo cliente de ID 1 e todos os 5 pedidos tinham o ID 1, e isso quebra o método .getSingleResult() que precisa de apenas um resultado só como retorno da query. Depois disso eu achei q o método não fazia sentido, já que como uma mesma cliente pode ter vários pedidos, chamar um .getSingleResult() tem grandes chances de quebrar a aplicação se o cliente tiver > 1 pedidos, especialmente porque o método só retorna uma única instância de pedido. Para esse método fazer mais sentido, eu acho que além do parâmetro relacionado ao cliente, informações sobre o pedido deveriam vir, ou então retornar uma lista de pedidos feitos por aquele cliente, já que é estranho (para mim) tentar encontrar um cliente através de vários pedidos, para então precisar necessariamente retornar um único pedido dentre possivelmente vários pedidos diferentes que um mesmo cliente pode fazer. Eu imagino que tenha funcionado para o professor normalmente por ele só ter um cliente que fez apenas 1 pedido e ainda o ID do pedido ter sido igual ao ID do cliente passado como parâmetro.

De resto, esse método ficou meio estranho, então me corrija se eu estiver errado.

Como o objetivo do método é retornar um Pedido para que se acessemos o cliente daquele Pedido baseado no ID que passamos como parâmetro, eu fiz uma modificação no método:

public Pedido buscarPedidoComCliente(Long idCliente) {
        String jpql = "SELECT p FROM Pedido p JOIN FETCH p.cliente WHERE p.cliente.id = :idCliente";
        return em.createQuery(jpql, Pedido.class)
                .setParameter("idCliente", idCliente)
                .setMaxResults(1)
                .getSingleResult();
    }

Sendo assim, é muito provável que um cliente tenha mais de 1 pedido no BD. Se queremos apenas o nome, eu limito o resultado para a primeira ocorrência já que o pedido em si é irrelevante, só estamos usando ele para conseguir um cliente através de um ID que pesquisamos. Para manter o .getSingleResult() e evitar que ele retorne uma lista de Pedidos (algo que poderia acontecer facilmente por clientes poderem ter mais 1 pedido), apenas adicionei o .setMaxResults(1) para ele pegar o primeiro resultado e voalá.

1 resposta

Oi Italo,

No exemplo que mostrei na aula eu estava carregando o pedido de id = 1 no banco de dados, independente do cliente associado a esse pedido.

O JOIN FETCH foi apenas para na mesma querie carregar os dados do cliente relacionado com esse pedido de id = 1.

Na consulta que você fez, você está carregando o pedido que pertence ao cliente de id = 1, sendo que nesse caso podem existir vários pedidos desse mesmo cliente no banco de dados, e por isso acontece a exception NonUniqueResultException.