Como construir uma API de gestão financeira com Java, Spring Boot, JPA, Hibernate e H2 - Parte I

Como construir uma API de gestão financeira com Java, Spring Boot, JPA, Hibernate e H2 - Parte I

Este artigo é destinado para todos aqueles que possuem conhecimento intermediário na linguagem de programação Java, incluindo também os conceitos e princípios da Programação Orientada a Objetos (POO) e conhecimentos conceituais básicos de SQL.

Aos que são iniciantes e entusiastas da linguagem, indico o conteúdo do Gabriel Reis Duarte, responsável por fazer o Guia inicial de Java dentro da plataforma da Revelo para quem está começando. Também indico aos iniciantes a seguinte formação, cheia de exercícios práticos, da Universidade de Helsinki: Java Programming.

Este artigo está repleto de referências. Não tenha medo de tirar um tempo para olhar ou ler na íntegra cada uma delas. Algumas estão em inglês, então também não tenha receio de utilizar ferramentas de tradução que vão te permitir um bom entendimento de algo que foi escrito em outro idioma.

Ao longo deste artigo, será iniciado a criação de uma API REST para gestão financeira, usando os seguintes Frameworks: Spring, JPA, Hibernate e H2, cada um deles possui um propósito específico que será apresentado mais a frente. O sistema tem como base o diagrama de exemplo a seguir:

Imagem I - Diagrama do sistema de gerenciamento de finanças.


Não se preocupe em entender todo o diagrama agora com esta primeira imagem, tudo será apresentado aos poucos ao longo do artigo.

Devido à complexidade e profundidade do conteúdo, este artigo será dividido em três, portanto, segue o link para a segunda e para a terceira parte parte:

O projeto utilizado como base para este artigo se encontra neste repositório do GitHub.

Para que serve cada framework?

Antes de tudo, precisa-se entender o que é um framework e para que serve. Em poucas palavras, a tradução literal de “framework” é “ferramenta”, o framework é um conjunto de bibliotecas cheias de funções, estruturas e métodos que servem para facilitar o desenvolvimento de uma aplicação, nesse caso, serão utilizados frameworks diferentes para facilitar o desenvolvimento de partes diferentes do sistema.

Spring

O framework Spring possui diversas outras ferramentas dentro dele e, para este artigo, serão apresentados e utilizados apenas o Spring Boot e o Spring Web.

Spring Boot

O Spring Boot é responsável pela: configuração automática do projeto, usando como base as ferramentas de construção de projeto Maven ou Gradle;

Neste projeto, será utilizado Maven.

Spring Web

Utilizado para a criação de serviços da Web que utilizam o protocolo SOAP. Basicamente será necessário para que seja possível se comunicar utilizando as regras de mensageria adotadas pela Internet.

JPA

Utilizado para que seja possível persistir objetos Java utilizando da técnica de ORM em conjunto com o banco de dados H2.

Hibernate

Funciona em conjunto com o JPA também para realizar o mapeamento de objetos, visando persistir no banco de dados.

Sendo assim, qual seria a diferença entre o Hibernate e o JPA? Seria um bom ponto de pesquisa para que você leitor possa aprofundar posteriormente, mas, resumindo: o JPA é uma especificação Java sobre como se implementa um ORM e o Hibernate é o Framework em si que implementa o JPA e fornece funcionalidades de criação, leitura, atualização e deleção de objetos persistidos no banco de dados.

H2

É o banco de dados que será utilizado no projeto para persistir cada informação necessária nas respectivas tabelas. Esse banco de dados foi escrito em Java e foi escolhido devido à facilidade na utilização. Por ser um banco de dados em memória, não é necessário instalar nada no computador. É uma ferramenta muito comum para utilização de testes em Java devido à praticidade.

API de gestão financeira

A API vai servir para que um usuário consiga informar receitas e despesas, também podendo classificá-las de acordo com categorias criadas pelo próprio usuário. Cada categoria ou despesa também terá um status.

Projeto

Dentro deste capítulo estão concentrados todos os passos envolvendo o código do projeto e algumas explicações voltadas para a explicação das decisões tomadas.

O projeto será estruturado em três camadas:

1) Entidade

  • Local onde ficarão todas as classes que definem cada objeto que será utilizado pelo sistema. Exemplos: Usuario, Receita, Despesa.

2) Recurso

  • Local onde estarão todas as chamadas à API, responsáveis por receber a requisição e enviar uma resposta.

3) Serviço

  • Local onde estarão as regras lógicas que serão utilizadas para manusear as entidades e acessar os repositórios.

4) Repositório

  • Local onde será utilizado o JPA para acessar os dados que estarão armazenados no banco H2.
Imagem II - Diagrama da estrutura de organização do projeto.

Criando o projeto

Para facilitar a criação do projeto, recomendo a utilização do site oficial da Spring chamado Spring Initializr para inicializar um projeto utilizando Spring Boot.

1) Acesse o Spring Initializr;

2) Segue um exemplo de preenchimento das opções:

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.0.5 (dependendo da época, será necessário uma versão mais recente)
  • Group: br.com.caiocv18 (colocar o próprio site de maneira invertida)
  • Artifact: artigojava (informe o nome do projeto)
  • Name: artigojava (informe o nome do projeto novamente)
  • Packaging: Jar
  • Java: 17
  • Dependencies > ADD DEPENDECIES > Spring Web
GIF I - Criação do projeto utilizando Spring Initializr.


3) Clique em GENERATE;

4) Baixe o arquivo;

5) Descompacte em uma pasta de própria escolha;

6) Abra o IntelliJ ou uma IDE também de própria escolha;

7) Abra o projeto de acordo com a pasta escolhida;

8) Execute a aplicação:

GIF II - Executando a aplicação no navegador Web.


9) Acessar localhost:8080 pelo navegador de própria escolha;

ℹ️ Link do meu commit relacionado aos passos realizados acima: https://github.com/caiocv18/artigojava/commit/dfb28b7dc68f770a60fc77fc0b0cc6da4af7e9e9

Usuário

Imagem III - Entidade Usuário.


Para a classe Usuário, teremos apenas os atributos a seguir:

  • id;
  • nome;
  • email;
  • senha.

Com os métodos get e set para cada atributo.

Devido às anotações e funções que serão utilizadas, também se faz necessário a criação dos métodos equals e hashCode.

Criando a entidade Usuário

Siga os passos a seguir para a criação a primeira entidade, visando seguir a estrutura de projeto apresentada anteriormente:

1) Crie um pacote chamado entidades;

2) Crie a classe Usuario;

3) Adicione os atributos como private:

  • int id;
  • String nome;
  • String email;
  • String senha;

ℹ️ O atributo id será fundamental para a utilização de ORM e para persistir no banco de dados posteriormente.

4) Crie um construtor vazio;

ℹ️ Esse construtor é necessário devido ao uso do framework Hibernate. Para entender melhor, veja a discussão sobre esse assunto no Stack Overflow.

5) Crie um construtor com todos os atributos;

6) Gere os getters e setters;

7) Gere hashcode e equals (selecionar apenas o atributo de ID para fazer a comparação);

8) Implementar a interface Serializable;

ℹ️ Serializable serve para: transformar os objetos em cadeias de bytes para que os mesmos possam trafegar numa rede, serem gravados em arquivos e etc.

9) Adicione o número de série padrão sugerido pelo próprio IntelliJ para o Serializable.

Criando o recurso Usuário

1) Crie um pacote de recursos

2) Crie uma classe UsuarioRecurso

3) Adicione a anotação @RestController acima da classe

ℹ️ Controlador necessário para manipular a classe em questão e serializar o objeto gerado para que seja possível enviar e receber na web.


4) Adicione a anotação abaixo da anterior para @RequestMapping passando como parâmetro (value = "/usuarios")

5) Crie um método com base na tipagem ResponseEntity<T> onde é passado o tipo da entidade como no lugar de T: ResponseEntity<Usuario>
public ResponseEntity<Usuario> findAll{

}

6) Retorne um objeto novo, apenas para teste

Usuario novoUsuario  = new Usuario(1, "Caio", "caiocv18_dev@gmail.com","6199999999","12345")

return ResponseEntity.ok().body(u);

7) Adicione anotação para o tipo de requisição do método, colocando a Annotation @GetMapping

8) Por fim, a classe fica da seguinte forma:

package br.com.caiocv18.artigojava.recursos;

import br.com.caiocv18.artigojava.entidades.Usuario;

import org.springframework.http.ResponseEntity;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

@RestController

@RequestMapping(value = "/usuarios")

public class UsuarioRecurso {

@GetMapping

public ResponseEntity<Usuario> procurarTodos(){

Usuario novoUsuario = new Usuario(1, "Caio", "caiocv18_dev@gmail.com", "12345");

return ResponseEntity.ok().body(novoUsuario);

}

}

Ao final, será possível acessar [localhost:8080/usuarios](<http://localhost:8080/usuarios>) e visualizar o usuário que foi instanciado no exemplo acima:

Acessando

GIF III - o endpoint /usuarios.

ℹ️ Link do meu commit relacionado aos passos realizados acima: https://github.com/caiocv18/artigojava/commit/357d95e8b086380b03689eba5e44b9df6db8c036

Adicionando persistência de dados

Nesse momento, será necessário adicionarmos as dependências para a utilização do H2 e do JPA.

Para melhorar o funcionamento inicial, é uma boa ideia utilizar configurações de teste através de dados “mockados”, portanto, será criado um perfil de teste.

1) Inclua as dependências JPA e H2

2) Abrir o arquivo pom.xml

3) Colar as dependências abaixo:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-data-jpa</artifactId>

</dependency>

<dependency>

<groupId>com.h2database</groupId>

<artifactId>h2</artifactId>

<scope>runtime</scope>

</dependency>

4) Salvar o arquivo e esperar o Maven baixar as dependências

5) Edite o application.properties

6)Acrescentar as linhas abaixo:

spring.profiles.active=teste

spring.jpa.open-in-view=true

7) Crie o arquivo application-teste.properties

8) Acrescentar as linhas abaixo:

# DATASOURCE

spring.datasource.driverClassName=org.h2.Driver

spring.datasource.url=jdbc:h2:mem:testedb

spring.datasource.username=<seu nome de usuário>

spring.datasource.password=<pode deixar vazio ou colocar uma senha>

# H2 CLIENT

spring.h2.console.enabled=true

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

# JPA, SQL

spring.jpa.database-platform=org.hibernate.dialect.H2Dialect

spring.jpa.defer-datasource-initialization=true

spring.jpa.show-sql=true

spring.jpa.properties.hibernate.format_sql=true

⚠️ Não esqueça de substituir os dados de username e password.

ℹ️ Cada informação colocada nesse arquivo será utilizada para se conectar no banco de dados H2.

1) Em entidades/Usuario.java

2) Acrescente @Entity na classe;

ℹ️ Serve para que o JPA estabeleça uma ligação entre a entidade Usuario e a tabela de usuários que será criada no banco H2 quando o sistema for executado.

3) Acrescente @Table(name = "tb_usuario");

ℹ️ Anotação JPA com o intuito de especificar um nome para a tabela que será criada para persistir os dados da entidade em questão.

4) Acrescente @Id acima do id;

ℹ️ Ao utilizar junto da anotação do próximo item, serve para informar qual atributo da entidade será utilizado para representar o Id de cada objeto que também será um registro no banco de dados.

5) Acrescente @GeneratedValue(strategy = GenerationType.IDENTITY);

ℹ️ Especifica de que forma a chave primária deve ser gerada para a tabela e, nesse caso, será gerado através de uma coluna de auto incremento.

6) Altere o id de int para long.

ℹ️ Alteração necessária devido à adição das duas anotações anteriores.

Por fim, através do gif a seguir, veja de que forma é possível acessar o banco H2 depois de executar a aplicação e acessar o endpoint localhost:8080/h2-console:

GIF IV - Acessando o console do banco de dados H2.

ℹ️ Link do meu commit relacionado aos passos realizados acima: Criando e se conectando ao banco de dados H20173ea9

Criando o repositório Usuário

Para que seja possível acessarmos o banco e consequentemente acessarmos os dados que serão transferidos para as tabelas, será necessário criar uma interface voltada para isso:

  1. Crie um pacote repositorios;
  2. Crie uma interface UsuarioRepositorio;
  3. Colocar a interface para estender JpaRepository passando o tipo da entidade e o tipo do identificador (Exemplo: JpaRepository<User, Long>).

ℹ️ Não é necessário implementar os métodos pois o JPA Repository já os possui implementados de maneira suficiente para trabalhar com a entidade passada como parâmetro e com a tipagem de identificador utilizada.

Agora, combinando a questão dos dados de teste com a classe de repositório que acabou de ser criada:

1) Crie um pacote chamado config;

2) Crie uma classe chamada TesteConfig;

3) Adicione as anotações @Configuration e @Profile("teste");

4) Crie uma variável do tipo UsuarioRepositorio

ℹ️ Isso acaba causando uma injeção de dependência.

5) Adicione a anotação @Autowired;

ℹ️ Anotação utilizada para apontar uma injeção de dependência usando o Spring.

(O conceito por trás do funcionamento disso daria um artigo separado, mas o intuito aqui é apresentar cada etapa aos poucos). Caso esteja curioso para saber, acesse os seguintes links: - https://medium.com/@leonardogiuliani/autowired-e-a-injeção-de-dependência-do-spring-d8864cc9af50.

OBS: Vá com calma. Caso as explicações te assustem, tenha ciência de que está sendo abordado um conceito avançado e que demanda conhecimentos prévios antes de entender completamente o uso.

6) Implementar a interface CommandLineRunner para que a classe seja executada de maneira automática na inicialização;

7) Sobrescrever o método run da interface, criando usuários para popular o banco de dados:

Usuario usuario1 = new Usuario(null, "Caio", "caio@gmail.com", "988888888", "123456");

Usuario usuario2 = new Usuario(null, "Vinicius", "vinicius@gmail.com", "977777777", "123456");

userRepository.saveAll(Array.asList(usuario1, usuario2));

ℹ️ Retira-se o Id no momento da criação do usuário pois o próprio banco de dados vai se encarregar da geração do número

8) Crie um construtor sem o Id como parâmetro na classe entidades/Usuario.java.

Agora, é possível acessar o console do banco de dados H2 e ver que a tabela criada anteriormente foi populada com os dados de teste que foram acrescentados na classe TesteConfiguracao:

GIF V - Acessando o console do banco de dados H2 e visualizando os dados que foram inseridos.

ℹ️ Link do meu commit relacionado aos passos realizados acima: Preenchendo o banco de dados de forma automática2cb76d3

Criando o serviço Usuário

Recapitulando para que serve a camada de serviço, ela é utilizada para que o sistema se comunique de maneira completa com cada funcionalidade do sistema, sendo assim, serão implementadas duas funcionalidades, a de pesquisar todos os registros da tabela e a de pesquisar pelo Id:

1) Criar um pacote servicos

2) Criar uma classe UsuarioServico e colocá-la com a anotação de @Service

package br.com.caiocv18.artigojava.servicos;

import br.com.caiocv18.artigojava.entidades.Usuario;

import br.com.caiocv18.artigojava.repositorios.UsuarioRepositorio;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.List;

import java.util.Optional;

@Service

public class UsuarioServico {

@Autowired

private UsuarioRepositorio repositorio;

public List<Usuario> pesquisarTodos(){

return repositorio.findAll();

}

public Usuario procurarPorId(Long id){

Optional<Usuario> usuario = repositorio.findById(id);

return usuario.get();

}

}

3) Editar a classe UsuarioRecurso, adicionando uma chamada à função que acabou de ser criada na classe de serviço:

@GetMapping(value = "/{id}") public ResponseEntity<Usuario> procurarTodos(@PathVariable Long id){ Usuario usuario = service.findById(id); return ResponseEntity.ok().body(usuario); }

Sendo assim, ao procurar por um Id utilizando o parâmetro no próprio endpoint como no exemplo abaixo, será possível visualizar cada registro específico da tabela:

ℹ️ Exemplo: localhost:8080/usuarios/1

GIF VI - Consultando usuários no banco de dados passando o Id como parâmetro.


ℹ️ Link do meu commit relacionado aos passos realizados acima: Pegando os usuários do banco e adicionando a pesquisa por Id82ee17b

Conclusão

Depois de muitos parágrafos, commits, conceitos, da implementação do elemento Usuario em todas as camadas do sistema e de 30 minutos de leitura estimados, é um bom momento para digerir com calma todas as informações que foram apresentadas e checar se realmente foi possível consolidar todos os ensinamentos.

Com toda certeza, o sistema ainda não está pronto, apesar de já ter boas funcionalidades, incluindo a consulta por Id e a persistência no banco de dados utilizando mock.

O artigo com a implementação das demais entidades e os avanços em outras funcionalidades, continua na parte II:

Como construir uma API de gestão financeira utilizando Java, Spring Boot, JPA, Hibernate e H2 - Parte II

Após a apresentação de tantos conceitos também colocados em prática neste artigo, a parte II terá mais foco no avanço dos demais elementos do sistema, como Despesa, Receita, Categoria e Status.

A parte III estará voltada para a implementação do restante das letras do CRUD, para que seja possível adicionar, atualizar e deletar cada um dos elementos do sistema e de colocar a aplicação em um ambiente hospedado na nuvem utilizando o Heroku.

Como construir uma API de gestão financeira utilizando Java, Spring Boot, JPA, Hibernate e H2 - Parte III

Agradeço por chegar até aqui e te desejo sucesso nessa nova aventura utilizando Java, Spring, JPA, Hibernate e H2!

Te espero na parte II para continuarmos a implementação do sistema da API de gestão financeira.

Segue meu contato e meu site em caso de alguma dúvida, necessidade ou sugestão:

Referências

  1. Curso do Nélio Alves com diversos projetos utilizando Java disponível na Udemy

    Java COMPLETO 2023 Programação Orientada a Objetos +Projetos
  2. Curso de Programação em Java da Universidade de Helsinki

    About the course - Java Programming
  3. Guia inicial de Java do Gabriel Reis Duarte disponível na Revelo Community

    Guia inicial de Java
  4. O que é um framework

    O que é um framework
  5. Primeiros passos com o Spring Boot

    Primeiros passos com o Spring Boot
  6. Chat GPT
  7. Definição de IDE

    Ambiente de desenvolvimento integrado
  8. Ícones

    Free Icons and Stickers - Millions of images to download
  9. Spring Web Services

    Spring Web Services
  10. SOAP

    SOAP
  11. ORM - Object Relational Mapping

    What is an ORM – The Meaning of Object Relational Mapping Database Tools
  12. Hibernate

    O que é e porque devo utilizar o Hibernate?
  13. Diferença Hibernate e JPA

    Hibernate e JPA são a mesma coisa?

    Como criar um CRUD completo com Hibernate e JPA - Leia aqui
  14. Why does Hibernate require no argument constructor?

    Why does Hibernate require no argument constructor?
  15. Serialization in Java - Java Serialization

    Serialization in Java - Java Serialization | DigitalOcean
  16. The Spring @Controller and @RestController Annotations

    The Spring @Controller and @RestController Annotations | Baeldung
  17. JPA: Como usar a anotação @Entity

    JPA: Como usar a anotação @Entity
  18. Qual o objetivo de mocar os dados ? O que isso significa?

    Qual o objetivo de mocar os dados ? O que isso significa ? | Fórum Alura
  19. Spring Data JPA – @Table Annotation

    Spring Data JPA - @Table Annotation - GeeksforGeeks
  20. ID annotation

    ID annotation
  21. JPA: Como usar a anotação @GeneratedValue

    JPA: Como usar a anotação @GeneratedValue
  22. Por que (strategy = GenerationType.IDENTITY)?

    Por que (strategy = GenerationType.IDENTITY)? | Fórum Alura
  23. Injeção de dependência

    Injeção de dependência
  24. Entendendo injeção de dependência

    Entendendo injeção de dependência
  25. Autowired e a injeção de dependência do Spring

    Autowired e a injeção de dependência do Spring
  26. What Is a Spring Bean?

    What Is a Spring Bean? | Baeldung
  27. Introdução prática ao Spring Framework com uso de Anotações

    Introdução prática ao Spring Framework com uso de Anotações
  28. Heroku

    Cloud Application Platform | Heroku

💡
As opiniões e comentários expressos neste artigo são de propriedade exclusiva de seu autor e não representam necessariamente o ponto de vista da Revelo.

A Revelo Content Network acolhe todas as raças, etnias, nacionalidades, credos, gêneros, orientações, pontos de vista e ideologias, desde que promovam diversidade, equidade, inclusão e crescimento na carreira dos profissionais de tecnologia.