Thursday, August 20, 2015

Usando Criteria da JPA 2 com Spring Data JPA

A flexibilidade do Spring Data JPA para desenvolver componentes de persistência e acesso a dados não é novidade. Nesse post vou descrever como utilizar o Criteria da JPA 2.0 em conjunto com o Spring Data JPA para gerar consultas avançadas. Essa abordagem é uma outra alternativa comparada ao QueryDSL.

O contrato Specification determina que um predicado (condição SQL) é criado a partir dos elementos Root, CriteriaQuery e CriteriaBuilder. Esses três elementos fazem parte da API de Criteria do JPA 2, mas são controlados e injetados pelo Spring.

O trecho a seguir, demonstra uma Specification para aplicar o filtro da categoria na consulta da entidade Mercadoria:

public final class MercadoriaSpecification {

  public static Specification<Mercadoria> byNome(String name) {
    return new Specification<Mercadoria>() {
      @Override
      public Predicate toPredicate(Root<Mercadoria> root,
          CriteriaQuery<?> query, CriteriaBuilder builder) {
        return builder.like(root.<String>get("nome"), 
            String.format("%s%", name.trim()));
      }
    };
  }
  ...
}

Essa Specification será encaminhada para o repositório, no momento da consulta. Veremos isso depois de analisar o repositório.

A interface Repository, sofre uma pequena modificação. Ela deve estender a interface JpaSpecificationExecutor, veja:

@Repository
public interface MercadoriaRepository
    extends JpaRepository<Mercadoria, Long>, JpaSpecificationExecutor<Mercadoria> {
}

Através dessa extensão é possível utilizar Specification nas consultas da entidade. O próximo trecho é usar o repositório p/ fazer a consulta de Mercadoria(s) de acordo com o predicado definido na Specification:

@RestController
@RequestMapping(value="/")
public class MercadoriaController {

  @Autowired
  private MercadoriaRepository repository;

  @RequestMapping(method = RequestMethod.GET, value="/{nome}")
  public List<Mercadoria> listByNome(@PathVariable String nome) {
    Specification<Mercadoria> specification = MercadoriaSpecification.byNome(nome);
    return Lists.newArrayList(repository.findAll(specification));
  }
  ...
}

Além da interface Specification, o Spring Data JPA também oferece a classe Specifications para facilitar a composição de múltiplos predicados. Subi um gist no meu GitHub com os trechos de código desse post e um outro exemplo de consulta com vários predicados simulando um formulário de filtros.

A referência desse post vem do blog do Spring.io.

www.yaw.com.br

5 comments:

Alexandre Camilo said...

Meu amigo, li a documentação do spring sobre o assunto, a especificação do jpa e não consegui entender como implementar essa interface, juntamente com criteria. Em poucas linhas vocÊ tirou totalmente minhas dúvidas. Parabéns!

Hinotori said...

Valeu man... você é o cara

Unknown said...

Olá @edermag,

Uma ajuda, se puder.

Estou usando Spring Boot com Spring Data.

Tenho uma estrutura de classes onde eu preciso recuperar dados baseados em diversas entidades. Ex. Todos os alunos da turma Y da série X que estudam no turno da manhã.

Para resolver esse problema, primeiro criei consultas onde eu escrevia todo o SQL (@Query) e dizia para executar de forma nativa (nativeQuery = true).
Depois esbarrei num problema quando fiz a consultar ser paginada (@Pageable), porque não aceita queryes nativas. Para resolver adaptei a query para JPQL.
Agora me dei conta que posso estar fazendo algo simples, de forma complexa. Tem um jeito mais fácil? Seria usando Criteria? Com o Critéria eu consigo fazer filtros navegando pelas classes associadas?

Grande abraço.

Hinotori said...
This comment has been removed by the author.
Blogger said...

You should see how my pal Wesley Virgin's autobiography starts in this shocking and controversial video.

As a matter of fact, Wesley was in the military-and shortly after leaving-he revealed hidden, "self mind control" secrets that the government and others used to get everything they want.

As it turns out, these are the same secrets many celebrities (especially those who "come out of nowhere") and elite business people used to become wealthy and successful.

You've heard that you only use 10% of your brain.

That's mostly because the majority of your BRAINPOWER is UNCONSCIOUS.

Maybe that thought has even taken place INSIDE OF YOUR very own head... as it did in my good friend Wesley Virgin's head around seven years ago, while riding an unlicensed, garbage bucket of a car with a suspended license and on his banking card.

"I'm absolutely fed up with living payroll to payroll! Why can't I become successful?"

You've taken part in those conversations, ain't it so?

Your own success story is waiting to be written. All you have to do is in YOURSELF.

CLICK HERE TO LEARN WESLEY'S SECRETS