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!
Comments