Solucionado (ver solução)
Solucionado
(ver solução)
2
respostas

Consulta retorna valores repetidos.

Boa Tarde.

Durante os testes do meu desenvolvimento, percebi que o "Curso de Violão" está se repetindo na colsulta.

Isto ocorre somente no código que está utilizando a API de Critéria, desenvolvi um código sem utilizar a api e desta forma "Curso de Violão" não se repete.

Testei a API de critéria com o código original, fornecido pela Alura, e por outro que eu desenvolvi.

Segue o código abaixo:

public List<Produto> getProdutos(String nome, Integer categoriaId, Integer lojaId) {

        //Código Original

//        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
//        CriteriaQuery<Produto> query = criteriaBuilder.createQuery(Produto.class);
//        Root<Produto> root = query.from(Produto.class);
//
//        Path<String> nomePath = root.<String> get("nome");
//        Path<Integer> lojaPath = root.<Loja> get("loja").<Integer> get("id");
//        Path<Integer> categoriaPath = root.join("categorias").<Integer> get("id");
//
//        List<Predicate> predicates = new ArrayList<>();
//
//        if (!nome.isEmpty()) {
//            Predicate nomeIgual = criteriaBuilder.like(nomePath, nome);
//            predicates.add(nomeIgual);
//        }
//        if (categoriaId != null) {
//            Predicate categoriaIgual = criteriaBuilder.equal(categoriaPath, categoriaId);
//            predicates.add(categoriaIgual);
//        }
//        if (lojaId != null) {
//            Predicate lojaIgual = criteriaBuilder.equal(lojaPath, lojaId);
//            predicates.add(lojaIgual);
//        }
//
//        query.where((Predicate[]) predicates.toArray(new Predicate[0]));
//
//        TypedQuery<Produto> typedQuery = em.createQuery(query);
//        return typedQuery.getResultList();


////////////////////////////////////////////////////////////////////////////////////////////////////        


        //Desenvolvido somente com JPA


//        String jpql = "select p from Produto p ";
//        
//        if(categoriaId != null){
//            jpql += "join fetch p.categorias c";
//        }
//        
//        if(nome != null || categoriaId != null || lojaId != null) {
//            jpql += " where";
//
//            if(!nome.isEmpty()) {    
//                jpql += " p.nome like :pNome and";        
//            }
//            
//            if(categoriaId != null) {    
//                jpql += " c.id = :pCategoriaId and";        
//            }
//            
//            if(lojaId != null) {    
//                jpql += " p.loja.id = :pLojaId and";        
//            }
//        
//            jpql += " 1=1";
//            
//        }
//        
//        TypedQuery<Produto> query = em.createQuery(jpql, Produto.class);
//        
//        if(!nome.isEmpty()) {    
//            query.setParameter("pNome","%"+nome+"%");
//        }
//        
//        if(categoriaId != null) {    
//            query.setParameter("pCategoriaId", categoriaId);
//        }
//        
//        if(lojaId != null) {    
//            query.setParameter("pLojaId", lojaId);
//        }
//        
//        return query.getResultList();

///////////////////////////////////////////////////////////////////////////////////////////////////////    

        //Desenvolvido com Criteria API

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery <Produto> query = criteriaBuilder.createQuery(Produto.class);
        Root <Produto> root = query.from(Produto.class);

        Path <String> nomePath = root.<String>get("nome");

        Path <Integer> categoriaPath = root.join("categorias").<Integer>get("id");
        Path <Integer> lojaPath = root.<Loja>get("loja").<Integer>get("id");

        Predicate conjuncao = criteriaBuilder.conjunction();

//        List <Predicate> predicates = new ArrayList<>();

        if(!nome.isEmpty()) {
//            Predicate nomePredicate = criteriaBuilder.like(nomePath, "%"+nome+"%");
//            predicates.add(nomePredicate);
            conjuncao = criteriaBuilder.and(criteriaBuilder.like(nomePath, "%"+nome+"%"));
        }

        if(categoriaId != null) {
//            Predicate categoriaPredicate = criteriaBuilder.equal(categoriaPath, categoriaId);
//            predicates.add(categoriaPredicate);

            conjuncao = criteriaBuilder.and(conjuncao, criteriaBuilder.equal(categoriaPath, categoriaId));

        }

        if(lojaId != null) {
//            Predicate lojaPredicate = criteriaBuilder.equal(lojaPath, lojaId);
//            predicates.add(lojaPredicate);

            conjuncao = criteriaBuilder.and(conjuncao, criteriaBuilder.equal(lojaPath, lojaId));

        }

//        query.where((Predicate[]) predicates.toArray(new Predicate[0]));
//        TypedQuery<Produto> typedQuery = em.createQuery(query);

        TypedQuery<Produto> typedQuery = em.createQuery(query.where(conjuncao)); 

        return typedQuery.getResultList();        

    }

Onde será que estou errando?

2 respostas
solução!

Olá Anderson!

Peço desculpas pela demora.

Vamos lá:

1 - Me manda por favor o conteúdo das tabelas de produto e categoria. Pode ser um print por aqui mesmo ou uma URL com a imagem.

Gostaria de saber quantas categorias o "Curso de Violão" possui pois essa quantidade de categorias pode estar sendo a causa para o retorno dos dois registros do curso.

2 - Geralmente o problema de retornar mais linhas do que o esperado se dá por conta do distinct. Tente usa-lo na construção da sua Query:

...
Root<Produto> root = query.from(Produto.class);
query.distinct(true);
...

Veja se funciona pra ti!

Aguardo seu retorno.

Boa Noite Guilherme.

Inseri o código que você me sugeriu e funcionou. Já entendi o que ocorreu, foi realmente o relacionamento entre Produto e Categoria.

Muito Obrigado.