Neste tutorial, aprenderemoshow to project entity properties using JPA and Hibernate.
2. A entidade
Primeiro, vamos dar uma olhada na entidade que usaremos ao longo deste artigo:
@Entity
public class Product {
@Id
private long id;
private String name;
private String description;
private String category;
private BigDecimal unitPrice;
// setters and getters
}
Esta é uma classe de entidade simples que representa um produto com várias propriedades.
3. Projeções JPA
Embora a especificação JPA não mencione as projeções explicitamente, há muitos casos em que as encontramos no conceito.
Normalmente, uma consulta JPQL possui uma classe de entidade candidata. A consulta, em execução, cria objetos da classe candidata - preenchendo todas as suas propriedades usando os dados recuperados.
Mas, é possívelretrieve a subset of the properties of the entity, ou, isto é, aprojection dos dados da coluna.
Além dos dados da coluna,we can also project the results of grouping functions.
3.1. Projeções de coluna única
Suponhamos que queremos listar os nomes de todos os produtos. Em JPQL, podemos fazer isso incluindo apenasname na cláusulaselect:
Query query = entityManager.createQuery("select name from Product");
List
Porquewe are projecting a single column that happens to be of type String, we expect to get a list of Strings no resultado. Portanto, especificamos a classe candidata comoString no métodocreateQuery().
Como queremos projetar em uma única propriedade,we’ve used the Query.select() method. O que está aqui é qual propriedade queremos, então, em nosso caso, usaríamos a propriedadename de nossa entidadeProduct.
Agora, vamos dar uma olhada em um exemplo de saída gerado pelas duas consultas acima:
Product Name 1
Product Name 2
Product Name 3
Product Name 4
Observe queif we’d used the id property in the projection instead of name, the query would have returned a list of Long objects.
3.2. Projeções Multi-Colunas
Para projetar em várias colunas usando JPQL, só temos que adicionar todas as colunas necessárias à cláusulaselect:
Query query = session.createQuery("select id, name, unitPrice from Product");
List resultList = query.getResultList();
Mas, ao usar umCriteriaBuilder, teremos que fazer as coisas de maneira um pouco diferente:
Aqui,we’ve used the method multiselect() instead of select(). Usando esse método, podemos especificar vários itens a serem selecionados.
Outra mudança significativa é o uso deObject[]. When we select multiple items, the query returns an object array com valor para cada item projetado. Este é o caso do JPQL também.
Vamos ver como ficam os dados quando os imprimimos:
[1, Product Name 1, 1.40]
[2, Product Name 2, 4.30]
[3, Product Name 3, 14.00]
[4, Product Name 4, 3.90]
Além disso, podemos usarCriteriaBuilder.tuple() ouCriteriaBuilder.construct() para obter os resultados como uma lista de objetosTuple ou objetos de uma classe personalizada, respectivamente.
3.3. Projetando Funções Agregadas
Além dos dados da coluna, às vezes podemos querer agrupar os dados e usar funções de agregação, comocounteaverage.
Digamos que queremos encontrar o número de produtos em cada categoria. Podemos fazer isso usando a função agregadacount() em JPQL:
Query query = entityManager.createQuery("select p.category, count(p) from Product p group by p.category");
O uso de qualquer um dos itens acima produzirá uma lista de matrizes de objetos:
[category1, 2]
[category2, 1]
[category3, 1]
Além decount(),CriteriaBuilder fornece várias outras funções de agregação:
avg - Calcula o valor médio de uma coluna em um grupo
max - Calcula o valor máximo para uma coluna em um grupo
min - Calcula o valor mínimo para uma coluna em um grupo
least - Encontra o menor dos valores da coluna (por exemplo, em ordem alfabética ou por data)
sum - Calcula a soma dos valores da coluna em um grupo
4. Projeções de hibernação
Ao contrário do JPA, o Hibernate forneceorg.hibernate.criterion.Projection for projecting with a Criteria query. Ele também fornece uma classe chamadaorg.hibernate.criterion.Projections, uma fábrica para instânciasProjection.
4.1. Projeções de coluna única
Primeiro, vamos ver como podemos projetar uma única coluna. Usaremos o exemplo que vimos anteriormente:
Usamos o métodoCriteria.setProjection() para especificar a propriedade que queremos no resultado da consulta. Projections.property() does the same work for us as Root.get() did ao indicar a coluna a ser selecionada.
4.2. Projeções Multi-Colunas
Para projetar várias colunas, primeiro teremos que criar umProjectionList. _ProjectionList * _ * é um tipo especial deProjection que envolve outras projeções para permitir a seleção de vários valores.
Podemos criar um métodoProjectionListusing the Projections.projectionList(), como mostrarProduct'sidename:
Neste artigo, vimos como projetar propriedades de entidade usando JPA e Hibernate.
É importante notar queHibernate has deprecated its Criteria API from version 5.2 onwards in favor of the JPA CriteriaQuery API. Mas, isso ocorre apenas porque a equipe do Hibernate não tem tempo para manter duas APIs diferentes, que fazem praticamente a mesma coisa, em sincronia.
E, claro, o código usado neste artigo pode ser encontradoover on GitHub.