
E aí, coders! Beleza?
Se você trabalha com JPA e deseja ser mais produtivo, colocar serviços web no ar em poucos minutos (combinando com Spring Boot, claro hehe), esse post é pra você.
Primeira e mais importante pergunta:

Pois bem, Spring Data JPA é um projeto que está contido em outro projeto do Spring, o Spring Data. O Spring Data por sua vez, possui implementações para trabalhar com diversas outras tecnologias, seguem alguns exemplos:
- Spring Data LDAP
- Spring Data MongoDB
- Spring Data Redis
- Spring Data Gemfire
- Spring Data Apache Cassandra
- Entre outros…
No nosso caso, o projeto foi implementado para trabalhar essencialmente com JPA.
Já pensou em ter os métodos básicos de um CRUD (create, read, update, delete) com apenas uma linha de código? Não? Pois se você ainda não sabe como fazer isso, vai aprender aqui e se surpreender com o poder desse framework!

Aqui vou basear todos os exemplos em um projeto desenvolvido com SpringBoot, certo? Como o foco do artigo não é o SpringBoot e presumindo que você já sabe como executar esse tipo de projeto, vou deixar o código fonte que tomei como base disponível no fim do artigo, assim você pode ler a teoria, os conceitos e logo depois colocar a mão na massa (cá entre nós, é assim que mais se aprende… tentando, fazendo, errando e acertando – os bugs no código que o digam hahaha’)
Então começando pelo nosso POM.xml, as dependências necessárias serão as seguintes:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-datajpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
Iremos precisar de uma classe de inicialização. Segue modelo:
@SpringBootApplication
public class SpringDataJpaApplication {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
A classe de inicialização não contém nenhuma configuração mais específica, ela apenas “starta” a busca por Beans do Spring para instanciar todos adequadamente. E por Beans do Spring, entenda classes anotadas com @Component, @Service, @Respository, @RestController etc.
Classe de inicialização criada, iremos agora criar também a nossa entidade de exemplo e será uma classe chamada Livro. O código segue abaixo:
@Entity
public class Livro implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
private Long id;
private String titulo;
private String fraseMarcante;
private boolean lido;
private Date dataLancamento;
private int quantidadePaginas;
//não esquecer getters e setters
}
A partir desse ponto, vamos falar um pouco do problema que o Spring Data JPA ajuda a resolver, o que não é bem um problema mas pode vir a ser, caso você não tenha a prática de refatorar o seu código e nem esteja acostumado ou familiarizado com reaproveitamento e lógicas mais reduzidos.
O Spring Data JPA vai se encaixar na camada de dados da sua aplicação, camada essa que alguns chamam de DAO e outros chamam de repositório. Tipo biscoito e bolacha, sabe? hehe’ A camada de acesso a dados, se não for bem planejada, tende a possuir várias lógicas repetidas, código muito verboso e quase nada reaproveitado. Um exemplo disso é uma simples aplicação de cadastro de produtos, que pode ter alguns métodos com objetivos um tanto quanto parecidos, mas diferentes em alguns detalhes. Veja algumas possíveis consultas:
- Produtos com preço acima do valor X
- Produtos com preço abaixo do valor Y
- Produtos em ordem alfabética
- Produtos em ordem crescente de valor
- Produtos presentes no estoque
- Produtos em falta no estoque
- A lista só cresce…
Então, como descrito no início sobre os possíveis problemas, agora fica mais fácil entender o que pode ocorrer… códigos praticamente iguais, classes enormes, pouco legíveis e de difícil manutenção. E ainda existe a questão da falta de praticidade, do tempo que se perde e do retrabalho que muitas vezes esse tipo de situação gera. Pensando em todos esses contratempos, o Spring Data JPA veio facilitar (e muito) esse trabalho.
Agora voltando ao nosso projeto, vamos a mágica do Spring Data JPA, iremos criar nosso repositório LivroRepository com as operações básicas de um CRUD:
@Repository
public interface LivroRepository extends JpaRepository<Livro, Long>{
}
Pronto! Eis o nosso repositório com tudo que é necessário para salvar, buscar, atualizar ou deletar nosso livro.
Essa é aquela hora que…

Calma que eu já vou explicar…
Os métodos do CRUD estão aí, porém não visíveis, pois só serão “injetados” em tempo de execução pelo próprio Framework. Agora vamos criar uma controller com nossos endpoints para entender melhor. Segue então o código da classe LivroController:
@RestController
@RequestMapping("/livros")
public class LivroController {
@Autowired
private LivroRepository livrosRepository;
@GetMapping("/{id}")
public Optional<Livro> buscarPorId(@PathVariable Long id) {
return livrosRepository.findById(id);
}
@GetMapping
public List<Livro> buscarTodos() {
return livrosRepository.findAll();
}
@PostMapping
public Livro salvar(@RequestBody Livro livro) {
return livrosRepository.save(livro);
}
@PutMapping
public Livro atualizar(@RequestBody Livro livro) {
return livrosRepository.save(livro);
}
@DeleteMapping("/{id}")
public void deletar(@PathVariable Long id) {
livrosRepository.deleteById(id);
}
}
Explicando o controller rapidamente (já que não faz parte do foco do artigo), anotamos a classe com @RestController para sinalizar que ela será responsável por responder as requisições trafegando a nossa entidade Livro (@Controller) diretamente no corpo da requisição (@ResponseBody) em formato JSON ou XML. A annotation @RestController foi criada pelo Spring para combinar o trabalho das anotações Controller (mapeia a resposta para a view) e ResponseBody (escreve a resposta no corpo da requisição HTTP). O @RequestMapping no topo da classe é o path raiz do nosso serviço web, todos os serviços relacionados a livros devem ser chamados com o “/livros” na frente (caso não seja colocado, é provável que você receba um código 404 do servidor. A não ser que coincidentemente tenha um serviço disponível exatamente com o endereço requisitado). A annotation @Autowired está injetando o nosso repositório de livros na controller, afim de realizar a comunicação com a camada de dados. E por fim as anotações @GetMapping, @PostMapping, @PutMapping e @DeleteMapping, são similares a RequestMapping, porém já explicitam a natureza da requisição que será enviada ao servidor e que serão dos tipos GET, POST, PUT e DELETE respectivamente.
Com esse código da controladora acima, já é possível fazer os testes da nossa aplicação. Execute o projeto a partir da classe Application (clique com o botão direito do mouse em cima da área do código da classe, em seguida Run As -> Spring Boot App), como visto na imagem abaixo.

Se você obteve um resultado similar a mostrado abaixo no console, seu projeto iniciou com sucesso.

Os serviços ficaram disponíveis nas seguintes urls:
- POST para http://localhost:8080/livros – Salvar livro
- GET para http://localhost:8080/livros – Buscar todos os livros
- GET para http://localhost:8080/livros/{id} – Buscar livro por id
- PUT para http://localhost:8080/livros – Atualizar livro
- DELETE para http://localhost:8080/livros/{id} – Deletar livro por id
Não custa lembrar que localhost, só se a aplicação estiver sendo executada na sua máquina local, hein? Se for fazer o exemplo em algum servidor de nuvem ou outra plataforma, substitua pelo path raiz do servidor e a porta na qual a aplicação subiu.
Agora dando continuidade, vamos entender o conteúdo da interface LivroRepository e da classe LivroController e as possibilidades que traz o Spring Data JPA:
- Primeiro o nosso repositório, ele é bem simples e estende a interface JpaRepository. A interface JpaRepository contém todos os métodos necessários para a implementação de um CRUD e como dito anteriormente, disponibiliza os mesmos na aplicação em tempo de execução. Assim não é necessário implementá-los, a não ser que você tenha um método muito personalizado, o que ainda veremos mais a frente.
- O segundo passo foi a nossa controladora que também tem um código muito enxuto, onde apenas injeta uma instância do nosso repositório e mapeia todos os nossos endpoints através de annotations. Perceba os métodos save, findAll, findById e deleteById. Esses métodos estão todos presentes na interface JpaRepository e você não precisou escrever uma linha de código se quer para que já esteja funcionando.
Vamos testar?
Baixe e instale no seu computador a ferramenta POSTMAN, que é uma aplicação super prática e simples para testar serviços Restful enviando e tratando o retorno de requisições HTTP. Caso não queira baixar, existe uma extensão para o Google Chrome que você pode instalar clicando AQUI.
Agora basta iniciar o seu projeto SpringBoot, iniciar também o POSTMAN e começar a fazer as requisições. Seguem alguns exemplos:

Para facilitar a reprodução do exemplo acima, segue o passo-a-passo:
No combo de métodos HTTP, selecionar POST. Digitar a URL localhost:8080/livros no campo logo ao lado. Abaixo, selecionar a opção Body e trocar o tipo de corpo da requisição de Text para JSON(application/JSON). Logo em seguida, cole o corpo da requisição na área destinada, como na imagem acima.
Exemplo de requisição:
{
"titulo":"Livro Um",
"fraseMarcante": "Esta é uma frase marcante do livro um",
"lido":"true",
"dataLancamento":"2013-01-01",
"quantidadePaginas":"99"
}
Agora basta apertar em SEND para enviar e ver o resultado logo abaixo, contendo alguns detalhes como o HTTP Status Code (que deve ser 200 OK), tempo de resposta e tamanho dos dados, seguido do corpo do retorno. Note que nessa requisição especificamente não foi enviado o id do livro e a requisição retorna o identificador, indicando que o mesmo foi salvo com sucesso!

Se você conseguiu, parabéns! E se não conseguiu, não desanima, volta um pouco aí e revisa que você consegue.
Mas calma que não acabou, viu!?! Passando desse ponto, existem os outros endpoints para testar e praticar. A repetição é uma das melhores formas de internalizar um conhecimento. Então…

Você pode salvar outros livros apenas mudando os dados do exemplo que acabamos de testar e depois que tiver alguns (quase uma biblioteca hehe), pode testar também os outros serviços.
Envie um GET para a URL /livros e terá o seguinte resultado:

Agora teste os demais serviços e veja como são os corpos de retorno. Caso obtenha algum erro, se atente o código HTTP da resposta e aproveite para ficar por dentro do padrão utilizado, aprendendo o que cada código e grupos de código quer dizer. Aproveito e deixo esse LINK caso você queira saber mais sobre isso.
Restam os seguintes casos para testar: GET em /livros/{id}, PUT em /livros e DELETE em /livros/{id}.
Se você tiver alguma dificuldade ou não souber como fazer, deixe sua dúvida ou sugestão nos comentários que eu respondo logo que puder.
Chegamos ao fim da parte 1 do artigo sobre o Spring Data JPA, mas adianto que ainda tem muita coisa interessante para facilitar a sua vida com a camada de persistência do seu projeto. Na parte 2, vou falar sobre consultas por atributo, uso de cláusulas para realizar consultas mais complexas, query e modifyng annotation, ordenação, paginação, parâmetros indexados e nomeados, coleção de parâmetros e um bônus sobre projections para mapear consultas diretamente para um DTO (padrão Data Transfer Object).

Código fonte do projeto: https://github.com/DheCastro/spring-data-jpa
