Voltar
Por que eu devo ler este artigo:Este artigo tem como objetivo introduzir o leitor ao padrão de projeto Specification, elaborado por Eric Evans para a camada de persistência de dados. O objetivo central desse padrão é desacoplar os critérios de seleção de uma entidade de modo que eles possam ser usados separadamente ou de forma combinada para se montar consultas específicas com maior flexibilidade. A partir de uma implementação já predefinida no Spring-Data JPA para o padrão Specification, se torna mais simples seu uso, bastando ao desenvolvedor fornecer elementos básicos no processo de cada consulta que deve ser criada. Assim, este artigo é útil por demonstrar como trabalhar com o Specification junto ao Spring-Data JPA em busca de uma maior produtividade no desenvolvimento de aplicações com acesso a banco de dados.

Spring Data e o padrão Specification

O Spring Framework é uma ferramenta de grande sucesso dentro do mundo Java. Para alcançar esse reconhecimento, vários dos seus recursos são projetados com a finalidade de simplificar o dia a dia dos programadores, fazendo com que eles utilizem princípios básicos de orientação a objetos, como herança, polimorfismo, baixo acoplamento, alta coesão e reuso. Com a intenção de fornecer facilidades de implementação aos desenvolvedores, o Spring teve sua arquitetura desenvolvida com base em diversos padrões de projeto. Ao mesmo tempo, ele incentiva seus usuários na adoção de padrões para que eles obtenham uma maior qualidade e produtividade no desenvolvimento de suas aplicações. Esse incentivo pode ser visto em recursos como Injeção de Dependências, Inversão de Controle, Model View Controller (por meio do Spring MVC) e o padrão Repository (por meio do Spring-Data).

Esse último é uma excelente opção para desenvolver a camada de acesso a dados em aplicações Java. O padrão Repository, no Spring-Data, faz com que o desenvolvedor programe apenas interfaces com as assinaturas dos métodos de consulta. Deste modo, o Spring-Data se encarregará da implementação desses métodos em tempo de execução. Para isso, as consultas são basicamente escritas por palavras-chave adicionadas ao nome do método, ou então, por código JPQL incluído em uma anotação do tipo @Query em sua assinatura. As consultas via Repository podem, ainda, serem substituídas ou desenvolvidas paralelamente com o padrão de projeto Specification.

Esse padrão tem como objetivo flexibilizar as regras existentes na construção de consultas a bancos de dados. Por exemplo, um método básico de consulta poderia receber como argumento um objeto do tipo Integer para recuperar uma entidade por um id. Mas esse mesmo método, tendo um Integer como argumento, não poderia receber como parâmetro um objeto String na tentativa de recuperar uma entidade por nome. Dessa forma, um novo método de consulta precisaria ser implementado para aceitar um parâmetro do tipo String.

Pensando nisso, o Specification é empregado como uma solução que visa separar as regras usadas na criação das consultas, possibilitando ter, por exemplo, um único método na camada de persistência que execute as consultas planejadas. Nesse cenário, as regras são encapsuladas em objetos chamados de predicados, que executam um papel específico dentro do padrão: representar um argumento do método de consulta na camada de persistência.

Aproveitando essa facilidade, o Spring-Data JPA já oferece parte do padrão Specification implementado. Assim, se torna mais fácil para o desenvolvedor trabalhar com ele, sendo necessário apenas criar algumas classes que definem mais especificamente quais ações devem ser executadas. Esse processo será apresentado durante o artigo, para que o leitor tenha uma introdução ao uso do padrão de projeto Specification junto com o Spring-Data JPA.

Padrões de Projeto

Como este artigo tem o objetivo de abordar o padrão Specification, elaborado por Eric Evans, é interessante saber um pouco mais sobre o que são padrões de projeto. Apresentados pela primeira vez em 1977, os padrões foram criados por Christopher Alexander, que publicou um catálogo com cerca de 250 padrões que discutiam questões comuns da arquitetura civil, descrevendo em detalhes o problema e as justificativas de cada solução.

Com o tempo, a área de desenvolvimento de software também passou a ter os seus próprios padrões. Tais elementos surgiram com objetivos semelhantes aos propostos por Alexander, a saber: explorar um problema, buscar uma solução e fornecer um modelo a ser seguido por outros desenvolvedores para o uso dessa solução. Essa necessidade ocorreu devido à baixa qualidade encontrada nos códigos fontes, que demonstravam ser de difícil interpretação, reutilização e manutenção.

Os padrões de projeto se tornaram ainda mais populares com o advento da orientação a objetos, onde seu uso é considerado uma boa prática a ser seguida na busca por uma maior qualidade no desenvolvimento de software. Quando um software é construído com qualidade, ele vai proporcionar uma maior flexibilidade e organização, tornando mais fácil sua manutenção e atualizações futuras, assim como favorece a técnica de reuso, conceito muito importante que possibilita o reaproveitamento de código. Exatamente por isso existem vários padrões que primam por esse conceito, como é o caso do DAO (Data Access Object), Service Layer, Model-View-Controller, Repository, Specification, entre outros.

Predicados em JPA

No padrão de projeto Specification há uma regra definindo que as consultas devem ser construídas com base em predicados, um tipo de objeto que tem como objetivo armazenar uma condição ou um tipo de critério qualquer. Por exemplo, se um valor é igual, menor, maior ou igual a outro.

Antes de explorarmos o uso desse padrão junto ao Spring-Data JPA, vamos analisar como trabalhar com predicados em consultas criadas com a API Criteria da JPA (veja o BOX 1). Essa abordagem é importante para que seja possível perceber o quanto a implementação de Specification no Spring-Data facilita o uso de predicados.

Para isso, vamos supor que exista uma entidade chamada User, e dentro dela, dois atributos, nomeados como name e age, que serão parâmetros em uma consulta baseada em predicados via API Criteria, conforme o pseudocódigo encontrado na Listagem 1.

BOX 1. API Criteria
A API Criteria é uma API que faz parte da especificação JPA com o objetivo de definir consultas ao banco de dados de forma alternativa às consultas do modelo JPQL. Assim, enquanto uma JPQL é escrita via String, a consulta por Criteria é baseada em métodos de interface e classes.

A principal vantagem da API Criteria é que os erros na construção da consulta podem ser detectados mais cedo, isto é, em tempo de compilação, ao passo que as consultas baseadas em JPQL têm os erros de escrita detectados apenas em tempo de execução.

Apesar de ...

Quer ler esse conteúdo completo? Tenha acesso completo