Depois de compreender como funciona a persistência utilizando JPA e Hibernate, explorar o ciclo de vida das entidades, utilizar o EntityManager, escrever consultas JPQL e implementar uma camada DAO manualmente, chegamos ao último passo desta série.
Neste artigo iremos migrar nossa aplicação para o ecossistema Spring Boot, utilizando Spring Data JPA para simplificar o acesso aos dados sem abrir mão dos conceitos estudados até aqui.
Ao contrário do que muitos imaginam, o Spring Data JPA não substitui a JPA nem o Hibernate. Na realidade, ele utiliza essas tecnologias internamente, oferecendo uma camada de abstração que reduz significativamente a quantidade de código que precisamos escrever.
Se nos artigos anteriores construímos toda a infraestrutura manualmente para compreender como a persistência funciona, agora veremos como o Spring automatiza grande parte desse trabalho.
#🎯 Objetivos
Ao final deste artigo você deverá ser capaz de:
- criar um projeto Spring Boot utilizando o Spring Initializr;
- configurar uma aplicação Spring Boot para utilizar PostgreSQL;
- reutilizar entidades JPA já existentes em uma aplicação Spring;
- compreender o papel do Spring Data JPA;
- criar interfaces Repository;
- implementar uma API REST simples;
- realizar testes HTTP utilizando um cliente REST.
#📚 O que muda quando usamos Spring Boot?
Até aqui nossa aplicação possuía aproximadamente esta arquitetura:
Aplicação
↓
DAO
↓
EntityManager
↓
Hibernate
↓
JDBC
↓
PostgreSQL
Grande parte do código que escrevemos estava relacionada à infraestrutura:
- criação do
EntityManagerFactory; - gerenciamento do
EntityManager; - abertura e fechamento de transações;
- implementação das operações CRUD;
- gerenciamento da camada DAO.
No Spring Boot boa parte dessa infraestrutura passa a ser gerenciada automaticamente.
Nossa arquitetura passa a ser semelhante à seguinte:
Controller
↓
Service
↓
Repository (Spring Data JPA)
↓
Hibernate
↓
JDBC
↓
PostgreSQL
Perceba que continuamos utilizando Hibernate e JPA.
O que muda é que o Spring Boot configura automaticamente diversos componentes da aplicação.
#🌱 Criando o projeto Spring Boot
Abra o Spring Initializr (https://start.spring.io).
Utilize as seguintes configurações:
- Project: Maven
- Language: Java
- Spring Boot: versão estável mais recente
- Java: 21
- Empacotamento: Jar
Dependências:
- Spring Web
- Spring Data JPA
- PostgreSQL Driver
Após gerar o projeto, importe-o no VS Code.
Outra opção é utilizar os recursos da extensão Spring Boot Extension Pack do VS Code para criar o projeto diretamente do editor. Para isso, pressione Ctrl+Shift+P e digite Spring Initializr. Siga as instruções para criar o projeto com as mesmas configurações mencionadas acima.
#⚙️ Configurando o banco de dados
Ao contrário da aplicação anterior, não utilizaremos mais um arquivo persistence.xml.
Toda a configuração será realizada através do arquivo:
src/main/resources/application.properties
spring.datasource.url=jdbc:postgresql://localhost:5432/cursos_pweb1
spring.datasource.username=postgres
spring.datasource.password=123456
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
Observe que agora o Spring Boot cria automaticamente:
- DataSource
- EntityManagerFactory
- EntityManager
- gerenciamento de transações
Lembre-se de ajustar o nome do banco, usuário e senha conforme sua instalação do PostgreSQL.
#♻️ Reaproveitando as entidades
A boa notícia é que praticamente todas as entidades criadas nos artigos anteriores podem ser reaproveitadas.
As anotações
@Entity@Id@GeneratedValue@Column@ManyToOne@OneToMany
continuam exatamente iguais.
Em muitos casos será necessário apenas ajustar os imports para utilizar os pacotes corretos da Jakarta Persistence.
Isso demonstra uma das grandes vantagens da JPA: como ela é uma especificação padronizada, o código permanece praticamente inalterado ao migrarmos para o Spring Boot.
Crie um pacote entities dentro do pacote base da aplicação. Então mova todas as entidades definidas e mapeadas na Parte 3 para esse pacote. Ajuste a definição do pacote em cada classe e verifique se os imports estão corretos.
#📦 Adeus DAO, Olá Repository
Na Parte 3 implementamos manualmente uma interface DAO e sua implementação utilizando o EntityManager. No Spring Data JPA essa implementação deixa de ser necessária.
Crie um pacote repositories dentro do pacote base da aplicação. Em seguida, crie uma interface InstrutorRepository dentro desse pacote com a seguinte definição:
@Repository
public interface InstrutorRepository
extends JpaRepository<Instrutor, Long> {
}
No código acima, Instrutor é a entidade que será gerenciada e Long é o tipo do identificador da entidade. Só de criar essa interface, extendendo de JpaRepository, o Spring Data JPA já disponibiliza automaticamente os métodos básicos de persistência, como:
save()
findById()
findAll()
deleteById()
existsById()
Sem escrever nenhuma implementação. É exatamente aqui que percebemos a produtividade oferecida pelo Spring Data JPA.
Seguindo a mesma lógica, crie as interfaces Repository para as demais entidades da aplicação, todas estendendo de JpaRepository e dentro do pacote repositories. Usamos a convenção de nomenclatura NomeDaEntidadeRepository para facilitar a identificação da interface que gerencia cada entidade.
O padrão Repository é um dos padrões de projeto mais utilizados no desenvolvimento de aplicações Java. Ele define uma abstração para o acesso a dados, permitindo que a lógica de negócio interaja com os dados sem se preocupar com os detalhes de implementação do armazenamento e nem com o local de armazenamento.
#🧠 Consultas derivadas
Além dos métodos básicos, o Spring consegue criar consultas automaticamente apenas analisando o nome do método.
Por exemplo, crie a seguinte assinatura de método dentro da interface InstrutorRepository:
List<Instrutor> findByNomeContaining(String nome);
Sem escrever JPQL, o Spring gera automaticamente uma consulta equivalente a:
WHERE nome LIKE '%texto%'
Também podemos criar consultas personalizadas utilizando a anotação @Query, quando necessário.
#🌐 Criando nossa primeira API REST
Para disponibilizar os dados da aplicação pela Web criaremos um controlador REST. Crie um pacote controllers dentro do pacote base da aplicação. Em seguida, crie a classe InstrutorController com a seguinte definição:
@RestController
@RequestMapping("/instrutores")
public class InstrutorController {
@Autowired
private final InstrutorRepository repository;
@GetMapping
public List<Instrutor> listar() {
return repository.findAll();
}
@PostMapping
public Instrutor salvar(@RequestBody Instrutor instrutor) {
return repository.save(instrutor);
}
}
Breve explicação do código acima:
@RestController: define a classe como um controlador REST (ou seja, que retorna dados no formato JSON e não páginas HTML, observando sempre os métodos e códigos de status apropriados do HTTP);@RequestMapping("/instrutores"): define a rota base para todos os métodos do controlador;@Autowired: injeta automaticamente a dependência doInstrutorRepository;@GetMapping: define o método que será chamado quando uma requisição HTTP GET for feita para a rota/instrutores;@PostMapping: define o método que será chamado quando uma requisição HTTP POST for feita para a rota/instrutores;@RequestBody: indica que o corpo da requisição HTTP será convertido automaticamente para um objetoInstrutor.
Observe que não utilizamos:
EntityManager;- transações explícitas;
- implementação DAO.
O próprio Spring coordena esses componentes para nós.
#▶️ Executando a aplicação
Execute a classe principal gerada pelo Spring Boot. No VS Code, pressione Ctrl+Shift+P, digite Spring Boot e selecione a opção Spring Boot: Run. Em seguida, selecione a classe principal do projeto. Ou ainda, procure o ícone da extensão Spring Boot Dashboard na barra lateral do VS Code e clique no botão de play para iniciar a aplicação.
Caso tudo esteja configurado corretamente, a aplicação iniciará um servidor embarcado na porta 8080.
A API estará disponível em:
http://localhost:8080/instrutores
#🧪 Testando a API
Para validar nossa aplicação, vamos realizar dois testes simples utilizando um cliente REST como o Insomnia, Postman ou a extensão REST Client do VS Code.
#Teste 1 — Inserindo um instrutor
POST
http://localhost:8080/instrutores
Body:
{
"nome": "Carlos Eduardo",
"email": "carlos@example.com",
"biografia": "Especialista em Java."
}
Resultado esperado:
- código HTTP 201 Created (ou 200 OK, dependendo da implementação);
- objeto persistido retornado na resposta;
- registro criado no PostgreSQL.
#Teste 2 — Consultando todos os instrutores
GET
http://localhost:8080/instrutores
Resultado esperado:
[
{
"id": 1,
"nome": "Carlos Eduardo",
"email": "carlos@example.com",
"biografia": "Especialista em Java."
}
]
Agora confirme também o resultado diretamente no PostgreSQL.
Você perceberá que o Spring Data JPA executou automaticamente todas as operações necessárias utilizando o Hibernate internamente.
#📊 Comparando as abordagens
| JPA + Hibernate | Spring Data JPA |
|---|---|
| Configuração manual | Configuração automática |
| EntityManager explícito | Gerenciado pelo Spring |
| DAO implementado manualmente | Repository automático |
| Transações explícitas | Gerenciadas pelo Spring |
| CRUD implementado manualmente | CRUD pronto com JpaRepository |
#🎓 Encerrando a série
Ao longo desta série percorremos uma evolução bastante comum no desenvolvimento de aplicações Java.
Começamos entendendo as limitações do JDBC e os desafios do mapeamento objeto-relacional. Em seguida, estudamos os fundamentos da JPA, aprendemos como o Hibernate implementa essa especificação, exploramos o funcionamento do EntityManager, do contexto de persistência, das transações e da JPQL, além de construir manualmente uma camada DAO para compreender o que acontece por trás das abstrações.
Neste último artigo demos o passo final: migramos a aplicação para o ecossistema Spring Boot e Spring Data JPA, reutilizando praticamente todo o modelo de domínio desenvolvido anteriormente. Essa migração evidencia um ponto importante: o Spring Data JPA não substitui os conceitos estudados, mas os organiza e automatiza, permitindo que o desenvolvedor concentre seus esforços na lógica de negócio em vez da infraestrutura de persistência.
A partir deste ponto, você já possui uma base sólida para estudar tópicos mais avançados do ecossistema Spring, como camadas de serviço, validação com Bean Validation, tratamento centralizado de exceções, paginação, autenticação com Spring Security e desenvolvimento de APIs REST mais completas.
Boa jornada nos próximos projetos! 🚀