🚀 Capítulo 18: Camadas do Spring e JPA

🎯 Objetivo da Aula

Ao final desta aula, você será capaz de organizar uma aplicação Spring Boot no padrão de Camadas (Controller, Service, Repository) e utilizar o Spring Data JPA para salvar e buscar dados no banco H2 sem precisar escrever código SQL manualmente.


🏢 O Cenário Prático (Seu Desafio)

Você é o operador Tank a bordo da Nabucodonosor. O seu desafio é criar um sistema seguro para gerenciar o cadastro dos tripulantes e rebeldes da resistência de Zion. Você deve salvar os dados (Nome, Codinome e Status) em um banco de dados e organizar o código em camadas profissionais para que os Agentes da Matrix não consigam quebrar o sistema!


🧠 Fundamentos: A Teoria Traduzida

Em projetos reais, não colocamos todo o código em um arquivo só. Nós dividimos em camadas para manter o código organizado e fácil de manter:

  • Controller: É a porta de entrada. Recebe as requisições web (HTTP) e devolve as respostas (geralmente em JSON).
  • Service: É o cérebro. Contém as regras de negócio (ex: “não pode cadastrar rebeldes com codinomes duplicados”).
  • Repository: É o braço que mexe no banco de dados.
  • JPA / Hibernate: É uma tecnologia que transforma objetos Java em tabelas no banco automaticamente. Você não precisa escrever INSERT ou SELECT!

Arquitetura em Camadas

flowchart TD
    A["Cliente (Navegador/Postman)"] -->|Requisição HTTP| B["Controller"]
    B --> C["Service"]
    C --> D["Repository"]
    D --> E[("Banco H2")]

📖 Exemplo Guiado

Vamos criar a estrutura para gerenciar os rebeldes de Zion.

🛠️ Passo a Passo para Criar o Projeto no VS Code

  1. Abra o VS Code.
  2. Pressione as teclas Ctrl + Shift + P.
  3. Digite Spring Initializr: Create Maven Project e pressione Enter.
  4. Selecione a versão estável do Spring Boot e a linguagem Java.
  5. Digite o Group ID: com.matrix e o Artifact ID: zion.
  6. Selecione a versão do Java instalada na sua máquina.
  7. Dependências (MUITO IMPORTANTE): Busque e adicione estas 3 dependências: Spring Web, Spring Data JPA e H2 Database. Pressione Enter para confirmar.
  8. Escolha a pasta e abra o projeto.

📂 Estrutura Inicial de Pastas (Maven)

zion/
├── src/
│   └── main/
│       ├── java/
│       │   └── com/matrix/zion/
│       │       └── ZionApplication.java
│       └── resources/
│           └── application.properties
└── pom.xml

Siga os passos para criar os arquivos dentro da pasta com/matrix/zion/:

  1. Crie a classe de modelo Rebelde.java (a nossa entidade de banco):
package com.matrix.zion;
 
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
 
@Entity // Diz ao Spring que essa classe vira uma tabela no banco
public class Rebelde {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String codinome;
 
    // Construtores (Obrigatório ter o vazio para o JPA)
    public Rebelde() {}
    public Rebelde(String nome, String codinome) { this.nome = nome; this.codinome = codinome; }
 
    // Getters e Setters
    public Long getId() { return id; }
    public String getNome() { return nome; }
    public String getCodinome() { return codinome; }
}
  1. Crie a interface RebeldeRepository.java (acesso aos dados):
package com.matrix.zion;
 
import org.springframework.data.jpa.repository.JpaRepository;
 
// O JpaRepository já vem com métodos prontos como save() e findAll()!
public interface RebeldeRepository extends JpaRepository<Rebelde, Long> {
}
  1. Crie a classe RebeldeService.java (regras de negócio):
package com.matrix.zion;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
 
@Service // Diz que essa classe é a camada de serviço
public class RebeldeService {
 
    @Autowired // O Spring cria e injeta o objeto automaticamente
    private RebeldeRepository repository;
 
    public List<Rebelde> listarTodos() {
        return repository.findAll();
    }
 
    public Rebelde salvar(Rebelde rebelde) {
        return repository.save(rebelde);
    }
}
  1. Crie a classe RebeldeController.java (atendimento Web):
package com.matrix.zion;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
 
@RestController
public class PokemonController {
 
    @Autowired
    private RebeldeService service;
 
    @GetMapping("/rebeldes")
    public List<Rebelde> listar() {
        return service.listarTodos();
    }
 
    @PostMapping("/rebeldes")
    public Rebelde criar(@RequestBody Rebelde rebelde) {
        return service.salvar(rebelde);
    }
}

🕹️ Como Executar e Testar no VS Code

  1. Abra o arquivo ZionApplication.java.
  2. Clique em Run logo acima do método main.
  3. Abra o navegador e acesse: http://localhost:8080/rebeldes.

Resultado Esperado: Você verá uma lista vazia [] (se o banco acabou de subir) ou os rebeldes cadastrados em formato JSON. Para cadastrar um rebelde, você pode usar uma extensão como o Thunder Client no VS Code para enviar uma requisição POST para http://localhost:8080/rebeldes com o corpo (Body) em formato JSON:

{
  "nome": "Neo",
  "codinome": "The One"
}

🛠️ Prática Obrigatória 1

No arquivo src/main/resources/application.properties, adicione as configurações para habilitar o console web do banco H2:

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

Rode o projeto, acesse http://localhost:8080/h2-console no seu navegador e veja a tabela REBELDE criada automaticamente pelo JPA!


🛠️ Prática Obrigatória 2

Crie um novo método no RebeldeService e no RebeldeController para buscar um Rebelde pelo seu ID (utilizando o método repository.findById(id)).


📤 Instruções de Entrega (GitHub Desktop + Microsoft Teams)

Neste curso, você entregará suas atividades enviando o código para o seu repositório no GitHub usando o aplicativo GitHub Desktop. Siga o passo a passo detalhado:

  1. Verifique a estrutura: Certifique-se de que sua estrutura de pastas final está idêntica à mostrada abaixo.
  2. Abra o GitHub Desktop: Certifique-se de que o repositório do seu curso está selecionado no canto superior esquerdo.
  3. Visualize as alterações: Na aba Changes (à esquerda), você verá todos os arquivos que criou ou modificou nesta aula.
  4. Faça o Commit:
    • No campo Summary (na parte inferior esquerda), digite uma mensagem curta descrevendo o que fez, ex: Finaliza atividades do Capítulo 18.
    • Clique no botão azul Commit to main (ou o nome da sua branch).
  5. Envie para a Nuvem (Push): No topo da tela, clique no botão Push origin. Isso enviará seu código do seu computador para o seu perfil no GitHub.
  6. ⚠️ IMPORTANTE (Repositório Público): Para que o professor consiga corrigir, o seu repositório no GitHub DEVE SER PÚBLICO. Repositórios privados não podem ser visualizados por quem não foi convidado.
  7. Como entregar no Microsoft Teams:
    • Copie o link do seu repositório no GitHub (ex: https://github.com/seu-usuario/seu-repositorio).
    • Abra a tarefa correspondente no Microsoft Teams.
    • Clique no botão Adicionar trabalho (ou Add work).
    • Selecione a opção Link no menu lateral.
    • Cole o link do GitHub no campo “Endereço Web” e digite um texto (ex: Meu Repositório) no campo “Texto a ser exibido”.
    • Clique em Anexar.
    • MUITO IMPORTANTE: Clique no botão Entregar (ou Turn in) no canto superior direito para concluir o envio!

📂 Estrutura Final de Pastas

zion/
├── src/
│   └── main/
│       ├── java/
│       │   └── com/matrix/zion/
│       │       ├── ZionApplication.java
│       │       ├── Rebelde.java
│       │       ├── RebeldeRepository.java
│       │       ├── RebeldeService.java
│       │       └── RebeldeController.java
│       └── resources/
│           └── application.properties
└── pom.xml

💡 Checkpoint de Lógica

O que você acabou de fazer é o padrão de mercado (Enterprise Pattern). Dividir em camadas garante que se amanhã mudarmos a forma de acessar o banco, as regras de negócio e a Web continuam funcionando intactas!


🔥 Desafio de Fixação (Opcional)

Pesquise como criar um método de busca por codinome no Repository usando as convenções de nome do Spring Data (ex: List<Rebelde> findByCodinome(String codinome)).


🔑 Gabarito de Código/Fórmulas

Prática 1:

(Basta adicionar as linhas no arquivo de propriedades).

Prática 2:

No Controller:

@GetMapping("/rebeldes/{id}")
public Rebelde buscar(@PathVariable Long id) {
    return service.buscarPorId(id); // Você deve criar este método no Service também!
}

Desafio:

No Repository, basta declarar o método (sem implementar!):

public interface RebeldeRepository extends JpaRepository<Rebelde, Long> {
    List<Rebelde> findByCodinome(String codinome);
}

Capitulo Anterior | Proximo Capitulo