Construye una API de gestión financiera con Java, Spring Boot, JPA, Hibernate y H2 - Parte I

Construye una API de gestión financiera con Java, Spring Boot, JPA, Hibernate y H2 - Parte I

Este artículo está dirigido a aquéllos que tengan conocimientos intermedios del lenguaje de programación Java, incluyendo también los conceptos y principios de la Programación Orientada a Objetos (POO) y conocimientos conceptuales básicos de SQL.

Para aquellos que son principiantes y entusiastas de los idiomas, recomiendo el contenido de Gabriel Reis Duarte, quien hizo la Guía inicial de Java para quienes se inician en la materia. También recomiendo a los principiantes este curso de la Universidad de Helsinki lleno de ejercicios prácticos: Java Programming.

Este artículo está lleno de referencias. No temas tomarte el tiempo para mirar o leer cada uno de ellos en su totalidad (algunos están en inglés o en portugués).

A lo largo de este artículo, comenzaremos a crear una API REST para la gestión financiera utilizando los siguientes frameworks: Spring, JPA, Hibernate y H2, cada uno con un propósito específico que será presentado más adelante. El sistema tiene como base este diagrama:

Imagen I - Diagrama del sistema de manejo de finanzas.


No te preocupes por entender el diagrama completo con esta primera imagen: todo se irá mostrará poco a poco a lo largo del artículo.

Debido a la complejidad y profundidad del contenido, este artículo se dividirá en tres, por ello, aquí te dejo el enlace a la segunda y tercera parte (en portugués):

El proyecto utilizado como base para este artículo se puede encontrar en este repositorio de GitHub.

¿Para qué sirve cada framework?

En primer lugar, es necesario comprender qué es un framework y para qué sirve. En pocas palabras, la traducción literal de “framework” es “marco”. El framework es un conjunto de bibliotecas llenas de funciones, estructuras y métodos que sirven para facilitar el desarrollo de una aplicación. En este caso, se utilizarán diferentes frameworks para facilitar el desarrollo de diferentes partes del sistema.

Spring

Posee varias otras herramientas dentro y, para este artículo, solo se presentarán y utilizarán Spring Boot y Spring Web.

Spring Boot

Spring Boot es responsable de la configuración automática del proyecto, utilizando como base las herramientas de construcción del proyecto Maven o Gradle;

Aquí usaremos Maven, por cierto.

Spring Web

Se utiliza para la creación de servicios de la Web que emplean elprotocolo SOAP. Básicamente, será necesario comunicarse utilizando las reglas de mensajería adoptadas por Internet.

JPA

Se utiliza para que sea posible conservar objetos Java utilizando el ORM en conjunto con la base de datos H2.

Hibernate

También funciona en conjunto con JPA para realizar mapeo de objetos, con el objetivo de conservarlos en la base de datos.

Entonces, ¿cuál sería la diferencia entre Hibernate y JPA? Sería un buen punto de investigación para que tú, el lector, puedas profundizar más adelante, pero, en resumen: JPA es una especificación de Java sobre cómo implementar un ORM e Hibernate es el framework en sí que implementa JPA y proporciona creación, lectura, la actualización y eliminación de objetos persistieron en la base de datos.

H2

Es la base de datos que se utilizará en el proyecto para conservar cada información necesaria en las tablas respectivas. Fue escrita en Java y se eligió por su facilidad de uso. Al ser una base de datos en memoria, no es necesario instalar nada en la computadora. Es una herramienta muy común para realizar pruebas en Java debido a su practicidad.

API de gestión financiera

La API permitirá al usuario informar ingresos y gastos y clasificarlos según categorías creadas por el usuario. Cada categoría o gasto también tendrá un estado.

Proyecto

Este capítulo contiene todos los pasos que involucran el código del proyecto y algunas explicaciones destinadas a explicar las decisiones tomadas.

El proyecto se estructurará en estas capas:

1) Entidad

  • Ubicación de todas las clases que definen cada objeto que será utilizado por el sistema. Ejemplos: Usuario, Ingresos, Gastos.

2) Recurso

  • Ubicación donde estarán todas las llamadas a la API, responsable de recibir la solicitud y enviar una respuesta.

3) Servicio

  • Ubicación de las reglas lógicas que se utilizarán para manejar entidades y acceder a repositorios.

4) Repositorio

  • Ubicación donde se utilizará JPA para acceder a los datos que se almacenarán en la base de datos H2.
Imagen II - Diagrama de la estructura de organización del proyecto.

Creando el proyecto

Para facilitar la creación de proyectos, recomiendo utilizar el sitio web oficial de Spring llamado Spring Initializr para inicializar un proyecto usando Spring Boot.

1) Entra a Spring Initializr;

2) Aquí un ejemplo de rellenado de opciones:

  • Project: Maven
  • Language: Java
  • Spring Boot: 3.0.5 (verificar si hay una opción más reciente)
  • Group: br.com.caiocv18 (colocar tu propio sitio de forma invertida)
  • Artifact: artigojava (indica el nombre del proyecto)
  • Name: artigojava (indica el nombre del proyecto nuevamente)
  • Packaging: Jar
  • Java: 17
  • Dependencies > ADD DEPENDECIES > Spring Web
GIF I - Creación del proyecto utilizando Spring Initializr.


3) Clic en GENERATE;

4) Descarga el archivo;

5) Descomprime en una carpeta que elijas;

6) Abre IntelliJ o una IDE que prefieras;

7) Abre el proyecto según la carpeta elegida;

8) Ejecuta la aplicación:

GIF II - Ejecutando la aplicación en el navegador web.


9) Ingresar a localhost:8080 en tu navegador;

ℹ️ Link de mi commit relacionado con estos pasos: https://github.com/caiocv18/artigojava/commit/dfb28b7dc68f770a60fc77fc0b0cc6da4af7e9e9

Usuario

Imagen III - Entidad Usuario.


Para la clase usuario, tendremos estos atributos:

  • id;
  • nombre;
  • email;
  • contraseña.

Con los métodos get y set para cada atributo.

Debido a las anotaciones y funciones que se utilizarán, también es necesario crear los métodos equals y hashCode.

Creando la entidad Usuario

Sigue estos pasos para crear la primera entidad, con el objetivo de seguir la estructura del proyecto presentada anteriormente:

1) Crea un paquete llamado entidades;

2) Crea la clase Usuario;

3) Añade los atributos como private:

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

ℹ️ El atributo id será fundamental para utilizar ORM y persistir en la base de datos más tarde.

4) Crea un constructor vacío;

ℹ️ Ese construtor se necesita por el uso del framework Hibernate. Para entender mejor, ve la discusión sobre el tema en Stack Overflow.

5) Crea un constructor con todos los atributos;

6) Genera los getters y setters;

7) Genera hashcode e equals (seleccionar el atributo de ID para hacer la comparación);

8) Implementar la interfaz Serializable;

ℹ️ Serializable sirve para transformar los objetos en cadenas de bytes para que puedan transitar en una red, ser guardados en archivos, etc.

9) Agraga el número de serie patrón sugerido por IntelliJ para Serializable.

Creando el recurso Usuario

1) Crea un paquete de recursos

2) Crea una clase UsuarioRecurso

3) Agrega la anotación @RestController encima de la clase

ℹ️ Controlador necesario para manipular la clase en cuestión y serializar el objeto generado para que sea posible enviarlo y recibirlo en la web.


4) Añade la anotación debajo de la anterior para @RequestMapping, pasando como parámetro (value = "/usuarios")

5) Crea un método con base en la tipado ResponseEntity<T> donde el tipo de entidad se pasaen lugar de T: ResponseEntity<Usuario>
public ResponseEntity<Usuario> findAll{

}

6) Devolver un nuevo objeto, solo para probar.

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

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

7) Agrega anotación para el tipo de requisición del método, colocando la Annotation @GetMapping

8) La clase queda de la siguiente 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);

}

}

Al final, será posible acceder a [localhost:8080/usuarios](<http://localhost:8080/usuarios>) y visualizar el usuario del que se creó una instancia en el ejemplo anterior:

GIF III - Endpoint /usuarios.

ℹ️ Link de mi commit sobre estos pasos: https://github.com/caiocv18/artigojava/commit/357d95e8b086380b03689eba5e44b9df6db8c036

Agregando persistencia de datos

En este punto, necesitaremos agregar dependencias para usar H2 y JPA.

Para mejorar la operación inicial, es una buena idea utilizar configuraciones de prueba a través de datos simulados, por lo que se creará un perfil de prueba.

1) Incluye las dependencias JPA y H2

2) Abrir el archivo pom.xml

3) Pega las dependencias abajo:

<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) Guarda el archivo y espera que Maven baje las dependencias

5) Edita application.properties

6) Añade las líneas siguientes:

spring.profiles.active=teste

spring.jpa.open-in-view=true

7) Crea el archivo application-teste.properties

8) Inserta:

# 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

⚠️ No olvide reemplazar tu nombre de usuario y contraseña.

ℹ️ Cada información colocada en este archivo se utilizará para conectarse a la base de datos H2.

1) Ve a entidades/Usuario.java

2) Inserta @Entity en la clase;

ℹ️ Se utiliza para que JPA establezca un vínculo entre la entidad Usuario y la tabla de usuarios que se creará en la base de datos H2 cuando se ejecute el sistema.

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

ℹ️ Anotación JPA para especificar un nombre para la tabla que se creará para conservar los datos de la entidad en cuestión.

4) Inserta @Id encima del id;

ℹ️ Cuando se usa junto con la anotación del siguiente elemento, sirve para informar qué atributo de la entidad se usará para representar el Id de cada objeto, que también será un registro en la base de datos.

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

ℹ️ Especifica cómo se debe generar la clave principal para la tabla y, en este caso, se generará a través de una columna de incremento automático.

6) Altera el id de int por long.

ℹ️ Cambio necesario debido a la adición de las anotaciones anteriores.

Finalmente, con el siguiente gif verás cómo es posible acceder a la base de datos H2 después de ejecutar la aplicación y acceder al punto final localhost:8080/h2-console:

GIF IV - Accesando a la consola de la base de datos H2.

ℹ️ Link de mi commit sobre el tema: Criando e se conectando ao banco de dados H20173ea9

Creando el repositorio Usuario

Para poder acceder a la base de datos y en consecuencia acceder a los datos que serán transferidos a las tablas, será necesario crear una interfaz orientada a esto:

  1. Crea un paquete repositorios;
  2. Crea una interfaz UsuarioRepositorio;
  3. Coloca la interfaz para extender JpaRepository pasando el tipo de la entidade e identificador (ejemplo: JpaRepository<User, Long>).

ℹ️ No es necesario implementar los métodos ya que el Repositorio JPA ya los tiene suficientemente implementados para trabajar con la entidad pasada como parámetro y con el tipo de identificador utilizado.

Ahora, combinando el problema de los datos de prueba con la clase de repositorio que se acaba de crear:

1) Crea un paquete llamado config;

2) Crea una clase llamada TesteConfig;

3) Agrega las anotaciones @Configuration y @Profile("teste");

4) Crea una variable de tipo UsuarioRepositorio

ℹ️ Eso causa una inyección de dependencia.

5) Agrega la anotación @Autowired;

ℹ️ Anotación utilizada para señalar una inyección de dependencia usando Spring.

(El concepto detrás de cómo funciona esto sería un artículo aparte, pero la intención aquí es presentar cada paso poco a poco). Si tienes curiosidad por saberlo, visita: https://medium.com/@leonardogiuliani/autowired-e-a-injeção-de-dependência-do-spring-d8864cc9af50.

NOTA: Va con calma. Si las explicaciones te asustan, ten en cuenta que se está tratando un concepto avanzado y que requiere conocimientos previos antes de comprender plenamente su uso.

6) Implementa la interfaz CommandLineRunner para que la clase se ejecute de manera automática en la inicialización;

7) Sobreescribe el método run de la interfaz, creando usuarios para llenar la base de datos:

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));

ℹ️ El Id se elimina cuando se crea el usuario porque la propia base de datos será la encargada de generar el número.

8) Crea un constructor sin el Id como parámetro en la clase entidades/Usuario.java.

Ahora es posible acceder a la consola de la base de datos H2 y ver que la tabla creada anteriormente se llenó con los datos de prueba que se agregaron a la clase PruebaConfiguracion:

GIF V - Accesando a la consola de la base de datos H2 y visualizando los datos insertados.

ℹ️ Link de mi commit relacionado: Preenchendo o banco de dados de forma automática2cb76d3

Creando el servicio Usuario

Recapitulando, la capa de servicio sirve para que el sistema se comunique completamente con cada funcionalidad del sistema. Por lo tanto, se implementarán dos funcionalidades, la de buscar todos los registros de la tabla y la de buscar por Id:

1) Crear un paquete llamado servicios

2) Crear una clase UsuarioServicio y colocarla con la anotación 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 la clase UsuarioRecurso, añadiendo un llamado a la función que acaba de ser creada en la clase de servicio:

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

Por lo tanto, al buscar un Id utilizando el parámetro en el propio endpoint como en el ejemplo siguiente, será posible ver cada registro específico en la tabla:

ℹ️ Ejemplo: localhost:8080/usuarios/1

GIF VI - Consultando usuarios en la base de datos pasando el Id como parámetro.


ℹ️ Link de mi commit relacionado: Pegando os usuários do banco e adicionando a pesquisa por Id82ee17b

Conclusión

Después de muchos párrafos, commits, conceptos, la implementación del elemento Usuario en todas las capas del sistema y un estimado de 30 minutos de lectura, es un buen momento para digerir con calma toda la información que se presentó y comprobar si realmente fue posible consolidar todas las enseñanzas.

Ciertamente, el sistema aún no está listo, a pesar de que ya tiene buenas características, incluida la consulta por ID y la persistencia en la base de datos mediante simulacros.

El artículo con la implementación de otras entidades y avances en otras funcionalidades continúa en la parte II (en portugués):

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

Después de presentar tantos conceptos que también se ponen en práctica en este artículo, la parte II se centrará más en avanzar en los otros elementos del sistema, como Gastos, Ingresos, Categoría y Estado.

La parte III se centrará en implementar el resto de las letras CRUD, de modo que sea posible agregar, actualizar y eliminar cada uno de los elementos del sistema y colocar la aplicación en un entorno alojado en la nube utilizando Heroku.

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

¡Gracias por llegar hasta aquí y te deseo éxito en esta nueva aventura usando Java, Spring, JPA, Hibernate y H2!

Los espero en la parte II para que podamos seguir implementando el sistema API de gestión financiera.

Si tienes dudas, contáctame:

Referencias

  1. Curso de Nélio Alves con diversos proyectos utilizando Java, disponible en Udemy

    Java COMPLETO 2023 Programação Orientada a Objetos +Projetos
  2. Curso de Programación en Java de la Universidad de Helsinki

    About the course - Java Programming
  3. Guía inicial de Java de Gabriel Reis Duarte, disponible en Listopro Community.

    Guía inicial de Java
  4. Qué es un framework

    O que é um framework
  5. Primeros pasos con Spring Boot

    Primeros pasos con Spring Boot
  6. Chat GPT
  7. Definición de IDE

    Ambiente de desarrollo integrado
  8. Íconos

    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

    ¿Qué es y por qué debo utilizar Hibernate?
  13. Diferencia entre Hibernate y JPA

    Hibernate y JPA: ¿son lo mismo?

    Cómo crear un CRUD completo con Hibernate y JPA
  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: Cómo usar la anotación @Entity

    JPA: Cómo usar la anotación @Entity
  18. ¿Cuál es el objetivo de "mockar" los datos? ¿Qué significa?

    ¿Cuál es el objetivo de "mockar" los datos? ¿Qué significa?
  19. Spring Data JPA – @Table Annotation

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

    ID annotation
  21. JPA: Cómo usar la anotación @GeneratedValue

    JPA: Cómo usar la anotación @GeneratedValue
  22. Por qué (strategy = GenerationType.IDENTITY)?

    Por qué (strategy = GenerationType.IDENTITY)? | Fórum Alura
  23. Injección de dependencia

    Injección de dependencia
  24. Entendiendo inyección de dependencia

    Entendiendo inyección de dependencia
  25. Autowired y la inyección de dependencia de Spring

    Autowired y la inyección de dependencia de Spring
  26. What Is a Spring Bean?

    What Is a Spring Bean? | Baeldung
  27. Introducción prcática a Spring Framework con anotaciones

    Introducción práctica a Spring Framework con anotaciones
  28. Heroku

    Cloud Application Platform | Heroku
💡
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Listopro.

Listopro Community da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.