1
resposta

[Dúvida]Por que no ex 09, retorna uma lista de array de objetos?

Por que na solução do exercício 09, é retornada uma lista de array de objetos (Object[]) ao invés de uma lista de Categoria?

 @Query("SELECT c.nome, COUNT(p) FROM Produto p JOIN p.categoria c GROUP BY c.nome HAVING COUNT(p) > :quantidade")
List<**Object[]**> categoriasComMaisDe(@Param("quantidade") long quantidade);
1 resposta

Oi, Estudante.

A razão para o retorno ser uma List<Object[]> acontece porque a sua consulta não tá selecionando a entidade completa (o objeto Categoria inteiro), mas sim colunas específicas de tabelas diferentes ou resultados de funções de agregação.

Por que não retorna uma Lista de Categoria?

Quando você escreve SELECT c, o JPA consegue mapear cada linha do banco de dados para uma instância da classe Categoria. Mas, na sua consulta:

SELECT c.nome, COUNT(p) ...

Você está pedindo duas coisas distintas para cada linha do resultado:

  1. O nome da categoria (uma String).
  2. A quantidade de produtos (um Long).

Como o Java não tem uma classe padrão que combine "uma String e um Long" sem que você a tenha criado, o JPA utiliza a estrutura mais genérica possível para representar essa linha: um array de Object (Object[]).

  • array[0]: contém o nome (String).
  • array[1]: contém a contagem (Long).

Como tornar isso mais legível?

Trabalhar com Object[] pode ser confuso porque você precisa fazer conversões (casts) manuais e lembrar qual informação tá em cada índice do array. Existem duas formas de resolver isso:

1. Utilizando uma Interface (Projeção)

Você pode criar uma interface simples para que o Spring faça o mapeamento automático:

public interface CategoriaContagemDTO {
    String getNome();
    Long getQuantidade();
}

E no seu repositório:

@Query("SELECT c.nome AS nome, COUNT(p) AS quantidade FROM Produto p JOIN p.categoria c GROUP BY c.nome HAVING COUNT(p) > :quantidade")
List<CategoriaContagemDTO> categoriasComMaisDe(@Param("quantidade") long quantidade);

2. Utilizando um DTO (Data Transfer Object)

Você pode criar uma classe record ou uma classe comum com construtor e usar a palavra-chave new dentro da JPQL:

@Query("SELECT new com.exemplo.dto.CategoriaDTO(c.nome, COUNT(p)) FROM Produto p JOIN p.categoria c GROUP BY c.nome HAVING COUNT(p) > :quantidade")
List<CategoriaDTO> categoriasComMaisDe(@Param("quantidade") long quantidade);

Resumo do comportamento:

  • SELECT p FROM Produto p: Retorna Produto (Entidade completa).
  • SELECT p.nome, p.preco: Retorna Object[] (Dados soltos).
  • SELECT COUNT(p): Retorna Long (Valor único).

Espero ter ajudado.

Conteúdos relacionados
Alura Conte com o apoio da comunidade Alura na sua jornada. Abraços e bons estudos!