JP

14 de out de 20206 min

Spring Boot com Spring Data + JPA

Atualizado: 22 de fev de 2023

O Spring Data é um dos vários projetos do ecossistema Spring que visa facilitar acesso aos dados através da utilização de modelos e sem a necessidade de escrever códigos SQL.

Qualquer manipulação de dados pode ser feita através de interfaces Java resultando em um código muito mais compreensível e mais limpo.

Criando o projeto

Para este projeto vamos usar as seguintes dependências:

  • Spring Data JPA

  • H2 Database

  • Lombok

Acesse o site https://start.spring.io selecionando as dependências conforme abaixo

Escolha a versão Java que você utiliza e clique em Generate para gerar os arquivos e em seguida faça a importação do arquivo pom.xml para a sua IDE.

Maven

<?xml version="1.0" encoding="UTF-8"?>
 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 
<modelVersion>4.0.0</modelVersion>
 
<parent>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring-boot-starter-parent</artifactId>
 
<version>2.4.4</version>
 
<relativePath/> <!-- lookup parent from repository -->
 
</parent>
 
<groupId>com.blog.spring.data</groupId>
 
<artifactId>spring-data</artifactId>
 
<version>0.0.1-SNAPSHOT</version>
 
<name>spring-data</name>
 
<description>Demo project for Spring Boot</description>
 
<properties>
 
<java.version>8</java.version>
 
</properties>
 

 
<dependencies>
 
<dependency>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring-boot-starter-data-jpa</artifactId>
 
</dependency>
 

 
<dependency>
 
<groupId>com.h2database</groupId>
 
<artifactId>h2</artifactId>
 
</dependency>
 
<dependency>
 
<groupId>org.projectlombok</groupId>
 
<artifactId>lombok</artifactId>
 
<optional>true</optional>
 
</dependency>
 
<dependency>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring-boot-starter-test</artifactId>
 
<scope>test</scope>
 
</dependency>
 
</dependencies>
 

 
<build>
 
<plugins>
 
<plugin>
 
<groupId>org.springframework.boot</groupId>
 
<artifactId>spring-boot-maven-plugin</artifactId>
 
<configuration>
 
<excludes>
 
<exclude>
 
<groupId>org.projectlombok</groupId>
 
<artifactId>lombok</artifactId>
 
</exclude>
 
</excludes>
 
</configuration>
 
</plugin>
 
</plugins>
 
</build>
 
</project>

Sobre o projeto

Neste projeto vamos trabalhar com base na classe Employee. Faremos uma carga inicial para o H2 que é um banco de dados em memória e em seguida vamos explorar mais o Spring Data criando algumas consultas utilizando apenas uma Interface Java.

Classe Employee

A classe Employee representará o modelo principal do projeto

package com.blog.spring.data.springdata.model;
 

 
import lombok.AllArgsConstructor;
 
import lombok.Data;
 
import lombok.NoArgsConstructor;
 
import javax.persistence.Entity;
 
import javax.persistence.GeneratedValue;
 
import javax.persistence.GenerationType;
 
import javax.persistence.Id;
 

 
@Data
 
@AllArgsConstructor
 
@NoArgsConstructor
 
@Entity
 
public class Employee {
 

 
@Id
 
@GeneratedValue(strategy = GenerationType.AUTO)
 
private Long id;
 
private String firstName;
 
private String lastName;
 
private String position;
 

 
@Override
 
public String toString() {
 
return String.format("Employee [ID: %o," +
 
"FistName: %s," +
 
"LastName: %s," +
 
"Position: %s]",
 
getId(),
 
getFirstName(),
 
getLastName(),
 
getPosition());
 
}
 
}

Observações sobre a classe acima:

  • Anotação @Data

    • A anotação @Data é um recurso do Lombok que facilita bastante a criação de modelos deixando o código menos verboso. Perceba que não foi necessário criar os getters e setters das propriedades graças ao uso do Lombok.

  • @AllArgsConstructor e @NoArgsConstructor

    • Também são recursos do Lombok

      • @AllArgsConstructor:

        • Possibilita criar um construtor de forma implícita.

      • @NoArgsConstructor:

        • Não obriga a passagem de argumentos para o construtor.

  • @Entity

    • Recurso do JPA que possibilita identificar a classe Employee como uma entidade de banco de dados.

  • @Id

    • Recurso do JPA utilizado para identificar um campo que deverá ser um identificar único no modelo de dados. Em resumo, a classe Employee por ter sido anotada como @Entity representará uma entidade a nível de banco de dados/tabela para a aplicação, e o @Id permite criar o campo id como um identificador único, ou seja, uma chave primária da entidade Employee.

  • @GeneratedValue(strategy = GenerationType.AUTO)

    • Recurso que permite controlar a geração dos valores únicos para o campo Id. Perceba que é necessário escolher a estratégia para gerar estes valores. Isso depende de cada engine de banco de dados, neste caso estamos utilizando o H2, mas caso utilizamos Oracle, a estratégia seria GenerationType.SEQUENCE.

Criando o repositório EmployeeRepository

No contexto de projeto Java, utilizamos algumas convenções de nomes para identificar recursos, neste campo vamos criar uma classe que servirá como repositório de dados para a entidade Employee.

Para trabalhar com Spring Data, os repositórios são bem importantes e devem ser criados como Interfaces Java herdando a Interface CrudRepository veja o código abaixo.

package com.blog.spring.data.springdata.repository;
 

 
import com.blog.spring.data.springdata.model.Employee;
 
import org.springframework.data.repository.CrudRepository;
 
import org.springframework.stereotype.Repository;
 
import java.util.List;
 
import java.util.Optional;
 

 
@Repository
 
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
 

 
Optional<Employee> findById(Long id);
 

 
List<Employee> findByFirstName(String firstName);
 

 
List<Employee> findByLastName(String lastName);
 

 
List<Employee> findByPosition(String position);
 

 
List<Employee> findByFirstNameAndPosition(String firstName,
 
String position);
 
}

Entendendo em partes:

  • @Repository

    • Identifica esta interface como um repositório no contexto do Spring

  • CrudRepository

    • Herdar (extends) a interface CrudRepository possibilita utilizar os recursos oferecidos pelo Spring Data. Neste caso é necessário passar como parâmetro a entidade (Employee) e o tipo do identificador único da classe Employee, que seria o campo id (Long)

  • Métodos

    • Esta é a parte mais importante deste Post. Perceba que para cada método se inicia com findBy e em seguida o nome do campo da classe Employee combinada ou não com um operador (AND) e um parâmetro. Todos estes métodos equivale a uma consulta SQL, perceba que não foi necessário criar scripts SQL de forma explicita. Isso é um dos recursos mais poderosos quando se utiliza Spring Data.

  • Optional<Employee> findById(Long id)

    • Retorno: Um objeto do tipo Employee

    • SQL: select * from Employee where id = ?

  • List<Employee> findByFirstName(String firstName)

    • Retorno: Uma lista de objetos do tipo Employee

    • SQL: select * from Employee where firstName = "?"

  • List<Employee> findByLastName(String lastName)

    • Retorno: Uma lista de objetos do tipo Employee

    • SQL: select * from Employee where lastName = "?"

  • List<Employee> findByPosition(String position)

    • Retorno: Uma lista de objetos do tipo Employee

    • SQL: select * from Employee where position = "?"

  • List<Employee> findByFirstNameAndPosition(String firstName, String position)

    • Retorno: Uma lista de objetos do tipo Employee

    • SQL: select * from Employee where firstName = "?" and position = "?"
       

Creio que agora está mais claro o funcionamento do Spring Data, agora vamos explorar na prática.

Criando a classe EmployeeService

Nesta classe criaremos a parte negocial onde invocaremos o repositório criado anteriormente.

package com.blog.spring.data.springdata.service;
 

 
import com.blog.spring.data.springdata.model.Employee;
 
import com.blog.spring.data.springdata.repository.EmployeeRepository;
 
import org.springframework.stereotype.Service;
 
import java.util.ArrayList;
 
import java.util.List;
 

 
@Service
 
public class EmployeeService {
 

 
static EmployeeRepository employeeRepository;
 

 
public EmployeeService(EmployeeRepository
 
employeeRepository){
 
this.employeeRepository = employeeRepository;
 
}
 

 
public static void populateEmployeeToDataBase(){
 

 
List<Employee> employees = new ArrayList<>();
 

 
employees.add(new Employee(1L,
 
"Monica",
 
"Silva",
 
"Director"));
 

 
employees.add(new Employee(2L,
 
"Jessica",
 
"Reies",
 
"Coordinator"));
 

 
employees.add(new Employee(3L,
 
"Milena",
 
"Torres",
 
"Dev"));
 

 

 
employees.add(new Employee(4L,
 
"Maura",
 
"Sanches",
 
"Dev"));
 

 
employeeRepository.saveAll(employees);
 
}
 

 

 
public void runQueries(){
 

 
populateEmployeeToDataBase();
 

 
employeeRepository.findById(3L)
 
.ifPresent(System.out::println);
 

 
employeeRepository.findByFirstName("Monica")
 
.ifPresent(System.out::println);
 

 
employeeRepository
 
.findByFirstNameAndPosition(
 
"Maura",
 
"Dev")
 
.ifPresent(System.out::println);
 

 
employeeRepository.findByPosition("Dev")
 
.ifPresent(System.out::println);
 

 
}
 
}

A classe EmployeeService será responsável por popular na base uma lista de objetos do tipo Employee e executar os métodos para acesso a base na classe EmployeeRepository.

Executando o código

Para a execução do código, vamos criar a classe principal do projeto chamada SpringDataApplication.java, seguindo os padrões de um projeto Spring Boot.

package com.blog.spring.data.springdata;
 

 
import com.blog.spring.data.springdata.service.EmployeeService;
 
import org.springframework.boot.SpringApplication;
 
import org.springframework.boot.autoconfigure.SpringBootApplication;
 

 
@SpringBootApplication
 
public class SpringDataApplication {
 

 
private static EmployeeService employeeService;
 

 
public SpringDataApplication(EmployeeService
 
employeeService){
 
this.employeeService = employeeService;
 
}
 

 
public static void main(String[] args) {
 
SpringApplication.run(SpringDataApplication.class, args);
 
employeeService.runQueries();
 
}
 
}

Esta classe possui 2 particularidades:

  • A anotação @SpringBootApplication

    • Esta anotação permite identificar esta classe como a principal para o contexto do Spring Boot e será responsável por iniciar a aplicação

  • O método main

    • Método responsável pela inicialização da aplicação e para este tutorial a invocação do método runQueries que criamos anteriormente.

Resultado da execução

Employee [ID: 3,FistName: Milena,LastName: Torres,Position: Dev]

[Employee [ID: 1,FistName: Monica,LastName: Silva,Position: Director]]

[Employee [ID: 4,FistName: Maura,LastName: Sanches,Position: Dev]]

[Employee [ID: 3,FistName: Milena,LastName: Torres,Position: Dev], Employee [ID: 4,FistName: Maura,LastName: Sanches,Position: Dev]]

Todas estas linhas acima são resultados de consultas SQL de forma implícita executadas pelos métodos em que criamos na classe EmployeeRepository.

Percebeu o poder do Spring Data sem a necessidade de criar consultas SQL no código?


Material de estudo

Se quer aprender mais sobre o assunto e alcançar um alto nível de conhecimento, recomendo fortemente a leitura do(s) seguinte(s) livro(s):

Spring Microservices in Action (Versão Inglês) cobre os princípios de microserviços utilizando Spring, criação de aplicações Spring Boot utilizando Spring Cloud, resiliência, como fazer o deploy e exemplos da vida real com boas práticas de desenvolvimento.

Spring MVC Beginner's Guide: Beginner's Guide (Versão Inglês) cobre os conceitos fundamentais do Spring como a arquitetura, fluxos de requisições, Bean validation, como controlar os fluxos de exceções, utilização de REST e Ajax, Testes e muito mais. Este livro é uma excelente escolha para você que queira entender mais a fundo sobre os fundamentos do Spring. Spring é um Framework Java contendo diferentes projetos, sendo que Spring MVC é um deles. Adquirindo um bom fundamento de Spring MVC, você estará apto para atuar em desafios utilizando qualquer projeto do Framework Spring.

Learn Microservices with Spring Boot: A Practical Approach to RESTful Services using RabbitMQ, Eureka, Ribbon, Zuul and Cucumber (Versão Inglês) cobre as principais características do ecosistema Spring utilizando Spring Boot, como a criação de microserviços, arquitetura baseada em eventos, utilização de RabbitMQ como recurso de mensageria, criação de serviços RESTful e muito mais. Este livro é uma excelente escolha para você que deseja conhecer mais sobre o funcionamento e os recursos oferecidos pelo Spring Boot.

Use a cabeça: Java é um clássico onde qualquer iniciante no assunto deve ler e estudar. Neste livro você aprenderá sobre os principais pilares de Java como, orientação a objetos, criação de classes, interfaces e seu funcionamento, controlar exceções, objetos genéricos e muito mais. Se quer entrar de cabeça neste mundo, é uma excelente opção!

Java Efetivo escrito por Joshua Bloch e traduzido para o português, é um livro excelente para aqueles que possuem um pouco mais de experiência com Java mas que precisam aprofundar em detalhes mais específicos da linguagem como, quando e como usar específicos Padrões de Projeto ou Design Patterns, utilização de Lambdas e Streams, concorrências e serializações. Para aqueles que possuem mais de experiência, é um excelente material de consulta.

Curtiu? Até mais!

    0