Saltar a contenido

Semana 4 - Guía Completa para Crear un Proyecto Spring Boot con H2, PostgreSQL y MySQL

Paso 1: Crear un fork de:

https://github.com/jfinfocesde/act_b2_s4.git

1.1 Clonar el Repositorio

# Navegar a la carpeta donde deseas clonar el proyecto
cd /ruta/deseada/

# Clonar el repositorio (reemplaza con la URL real del fork)
git clone https://github.com/tu-usuario/act_b2_s4.git

# Navegar al directorio del proyecto
cd act_b2_s4.git

1.2 Abrir el Proyecto en tu IDE

  • IntelliJ IDEA: File → Open → Seleccionar el directorio del proyecto
  • VS Code: File → Open Folder → Seleccionar el directorio del proyecto
  • Eclipse: File → Import → Existing Maven Projects

Paso 2: Estructura del Proyecto

La estructura final debe ser:

src/main/java/com/example/demo/
├── DemoApplication.java
├── model/
│   └── User.java
├── repository/
│   └── UserRepository.java
├── service/
│   ├── UserService.java
│   └── UserServiceImpl.java
└── controller/
    └── UserController.java

Paso 3: Crear los Paquetes

3.1 Crear Paquetes en tu IDE

  1. En src/main/java, crea el paquete base: com.example.demo
  2. Dentro del paquete base, crea los siguientes paquetes:
  3. model
  4. repository
  5. service
  6. controller

Paso 4: Crear la Clase Modelo

4.1 Crear User.java en model/

package com.example.demo.model;

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, length = 100)
    private String name;

    @Column(nullable = false, unique = true, length = 100)
    private String email;

    @Column(length = 20)
    private String phone;

    // Constructores
    public User() {}

    public User(String name, String email, String phone) {
        this.name = name;
        this.email = email;
        this.phone = phone;
    }

    // Getters y Setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", email='" + email + '\'' +
                ", phone='" + phone + '\'' +
                '}';
    }
}

Paso 5: Crear el Repositorio

5.1 Crear UserRepository.java en repository/

package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {

    // Métodos personalizados
    List<User> findByNameContainingIgnoreCase(String name);
    List<User> findByEmailContainingIgnoreCase(String email);
    boolean existsByEmail(String email);
}

Paso 6: Crear la Capa de Servicio

6.1 Crear UserService.java en service/

package com.example.demo.service;

import com.example.demo.model.User;

import java.util.List;
import java.util.Optional;

public interface UserService {

    List<User> getAllUsers();
    Optional<User> getUserById(Long id);
    User saveUser(User user);
    User updateUser(Long id, User user);
    void deleteUser(Long id);
    List<User> findByName(String name);
    List<User> findByEmail(String email);
    boolean existsByEmail(String email);
}

6.2 Crear UserServiceImpl.java en service/

package com.example.demo.service;

import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }

    @Override
    public Optional<User> getUserById(Long id) {
        return userRepository.findById(id);
    }

    @Override
    public User saveUser(User user) {
        if (userRepository.existsByEmail(user.getEmail())) {
            throw new RuntimeException("El email ya está registrado");
        }
        return userRepository.save(user);
    }

    @Override
    public User updateUser(Long id, User user) {
        Optional<User> existingUser = userRepository.findById(id);
        if (existingUser.isPresent()) {
            User updatedUser = existingUser.get();
            updatedUser.setName(user.getName());
            updatedUser.setEmail(user.getEmail());
            updatedUser.setPhone(user.getPhone());
            return userRepository.save(updatedUser);
        } else {
            throw new RuntimeException("Usuario no encontrado con id: " + id);
        }
    }

    @Override
    public void deleteUser(Long id) {
        if (userRepository.existsById(id)) {
            userRepository.deleteById(id);
        } else {
            throw new RuntimeException("Usuario no encontrado con id: " + id);
        }
    }

    @Override
    public List<User> findByName(String name) {
        return userRepository.findByNameContainingIgnoreCase(name);
    }

    @Override
    public List<User> findByEmail(String email) {
        return userRepository.findByEmailContainingIgnoreCase(email);
    }

    @Override
    public boolean existsByEmail(String email) {
        return userRepository.existsByEmail(email);
    }
}

Paso 7: Crear el Controlador

7.1 Crear UserController.java en controller/

package com.example.demo.controller;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/users")
@CrossOrigin(origins = "*")
public class UserController {

    @Autowired
    private UserService userService;

    // Obtener todos los usuarios
    @GetMapping
    public ResponseEntity<List<User>> getAllUsers() {
        List<User> users = userService.getAllUsers();
        return new ResponseEntity<>(users, HttpStatus.OK);
    }

    // Obtener usuario por ID
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        Optional<User> user = userService.getUserById(id);
        if (user.isPresent()) {
            return new ResponseEntity<>(user.get(), HttpStatus.OK);
        } else {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    // Crear nuevo usuario
    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        try {
            User newUser = userService.saveUser(user);
            return new ResponseEntity<>(newUser, HttpStatus.CREATED);
        } catch (RuntimeException e) {
            return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
        }
    }

    // Actualizar usuario
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User user) {
        try {
            User updatedUser = userService.updateUser(id, user);
            return new ResponseEntity<>(updatedUser, HttpStatus.OK);
        } catch (RuntimeException e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    // Eliminar usuario
    @DeleteMapping("/{id}")
    public ResponseEntity<HttpStatus> deleteUser(@PathVariable Long id) {
        try {
            userService.deleteUser(id);
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        } catch (RuntimeException e) {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    // Buscar usuarios por nombre
    @GetMapping("/search/name/{name}")
    public ResponseEntity<List<User>> findByName(@PathVariable String name) {
        List<User> users = userService.findByName(name);
        return new ResponseEntity<>(users, HttpStatus.OK);
    }

    // Buscar usuarios por email
    @GetMapping("/search/email/{email}")
    public ResponseEntity<List<User>> findByEmail(@PathVariable String email) {
        List<User> users = userService.findByEmail(email);
        return new ResponseEntity<>(users, HttpStatus.OK);
    }
}

Paso 8: Configuración de la Aplicación Base

8.1 Verificar DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Paso 9: Configuración para H2 Database

9.1 Agregar dependencias en pom.xml (si no existen)

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

9.2 Configurar application.properties para H2

# Configuración de H2 Database
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=

# Configuración de JPA/Hibernate
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

# Configuración de H2 Console
spring.h2.console.enabled=true
spring.h2.console.path=/h2-console

# Configuración del servidor
server.port=8080

Paso 10: Probar con H2 Database

10.1 Ejecutar la aplicación utilizando la extensión Spring Boot Extension Pack

10.2 Probar endpoints con curl o Postman

# Crear usuarios
curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Juan Pérez","email":"juan@email.com","phone":"123456789"}'

curl -X POST http://localhost:8080/api/users \
  -H "Content-Type: application/json" \
  -d '{"name":"María García","email":"maria@email.com","phone":"987654321"}'

# Obtener todos los usuarios
curl -X GET http://localhost:8080/api/users

# Obtener usuario por ID
curl -X GET http://localhost:8080/api/users/1

# Actualizar usuario
curl -X PUT http://localhost:8080/api/users/1 \
  -H "Content-Type: application/json" \
  -d '{"name":"Juan Pérez Actualizado","email":"juan.actualizado@email.com","phone":"111111111"}'

# Buscar por nombre
curl -X GET http://localhost:8080/api/users/search/name/Juan

# Acceder a H2 Console para Ver la Base de Datos
Para ejecutar y visualizar la base de datos H2:
1. Asegúrate de que `spring.h2.console.enabled=true` esté en `application.properties`.
2. Ejecuta la aplicación con `mvn spring-boot:run`.
3. Abre un navegador y ve a `http://localhost:8080/h2-console`.
4. En la consola H2, ingresa:
   - JDBC URL: `jdbc:h2:mem:testdb`
   - User Name: `sa`
   - Password: (deja en blanco)
5. Haz clic en "Connect".
6. Ahora puedes explorar tablas, ejecutar queries y ver datos.

Paso 11: Configuración para PostgreSQL

11.1 Agregar dependencia de PostgreSQL en pom.xml

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <scope>runtime</scope>
</dependency>

11.2 Crear base de datos en PostgreSQL

-- Conectarse a PostgreSQL y ejecutar:
CREATE DATABASE demo_springboot;
CREATE USER demo_user WITH PASSWORD 'demo_password';
GRANT ALL PRIVILEGES ON DATABASE demo_springboot TO demo_user;

11.3 Configurar application-postgresql.properties

# Configuración de PostgreSQL
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=
spring.datasource.driver-class-name=org.postgresql.Driver

# Configuración de JPA/Hibernate
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

# Configuración adicional de PostgreSQL
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

Paso 12: Configuración para MySQL

12.1 Agregar dependencia de MySQL en pom.xml

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
    <scope>runtime</scope>
</dependency>

12.2 Crear base de datos en MySQL

-- Conectarse a MySQL y ejecutar:
CREATE DATABASE demo_springboot;
CREATE USER 'demo_user'@'localhost' IDENTIFIED BY 'demo_password';
GRANT ALL PRIVILEGES ON demo_springboot.* TO 'demo_user'@'localhost';
FLUSH PRIVILEGES;

12.3 Configurar application-mysql.properties

# Configuración de MySQL
spring.datasource.url=jdbc:mysql://localhost:3306/demo_springboot?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=demo_user
spring.datasource.password=demo_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

# Configuración de JPA/Hibernate
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

# Configuración adicional de MySQL
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect

Paso 13: Configuración Principal

13.1 Crear application.properties principal

# Perfil activo por defecto (puede ser h2, postgresql o mysql)
spring.profiles.active=h2

# Configuración general del servidor
server.port=8080
server.servlet.context-path=/api

# Configuración de logging
logging.level.com.example.demo=DEBUG
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

Paso 14: Pruebas Completas

14.1 Script de pruebas con curl

Crear archivo test-apis.sh:

#!/bin/bash

echo "=== PRUEBAS DE API REST ==="
BASE_URL="http://localhost:8080/api"

echo "1. Creando usuarios..."
curl -X POST $BASE_URL/usuarios \
  -H "Content-Type: application/json" \
  -d '{"nombre":"Usuario Test 1","email":"test1@example.com","telefono":"111111111"}'

echo -e "\n"

curl -X POST $BASE_URL/usuarios \
  -H "Content-Type: application/json" \
  -d '{"nombre":"Usuario Test 2","email":"test2@example.com","telefono":"222222222"}'

echo -e "\n"

echo "2. Obteniendo todos los usuarios..."
curl -X GET $BASE_URL/usuarios

echo -e "\n"

echo "3. Obteniendo usuario por ID..."
curl -X GET $BASE_URL/usuarios/1

echo -e "\n"

echo "4. Actualizando usuario..."
curl -X PUT $BASE_URL/usuarios/1 \
  -H "Content-Type: application/json" \
  -d '{"nombre":"Usuario Actualizado","email":"actualizado@example.com","telefono":"999999999"}'

echo -e "\n"

echo "5. Buscando por nombre..."
curl -X GET "$BASE_URL/usuarios/buscar/nombre/Usuario"

echo -e "\n"

echo "6. Eliminando usuario..."
curl -X DELETE $BASE_URL/usuarios/2

echo -e "\n"

echo "7. Verificando eliminación..."
curl -X GET $BASE_URL/usuarios

14.2 Ejecutar pruebas

chmod +x test-apis.sh
./test-apis.sh

Paso 15: Verificación Final

15.1 Verificar estructura del proyecto

Asegúrate de tener:

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── ejemplo/
│   │           └── demo/
│   │               ├── DemoApplication.java
│   │               ├── controller/
│   │               │   └── UsuarioController.java
│   │               ├── model/
│   │               │   └── Usuario.java
│   │               ├── repository/
│   │               │   └── UsuarioRepository.java
│   │               └── service/
│   │                   ├── UsuarioService.java
│   │                   └── UsuarioServiceImpl.java
│   └── resources/
│       ├── application.properties
│       ├── application-h2.properties
│       ├── application-mysql.properties
│       └── application-postgresql.properties
└── test/

15.2 Verificar funcionalidad

  1. H2: Ejecutar con spring.profiles.active=h2
  2. PostgreSQL: Ejecutar con spring.profiles.active=postgresql
  3. MySQL: Ejecutar con spring.profiles.active=mysql

15.3 Probar endpoints

  • POST /api/usuarios - Crear usuario
  • GET /api/usuarios - Listar usuarios
  • GET /api/usuarios/{id} - Obtener usuario por ID
  • PUT /api/usuarios/{id} - Actualizar usuario
  • DELETE /api/usuarios/{id} - Eliminar usuario
  • GET /api/usuarios/buscar/nombre/{nombre} - Buscar por nombre
  • GET /api/usuarios/buscar/email/{email} - Buscar por email