- Obtener información almacenada en la base de datos.
- Hacer uso de las anotaciones básicas de JPA para indicar qué objeto debe ser tratado como una entidad de base de datos.
- Aprender qué es un repositorio y los métodos por default que ofrece.
- Aprender a usar el método
Mappers.getMapper
cuando trabajamos conCommandLineRunner
.
- Tener instalado el IDE IntelliJ Idea Community Edition con el plugin de Lombok activado.
- Tener instalada la última versión del JDK 11 o 17.
- Tener instalada la herramienta Postman.
- Tener instalada la base de datos MySQL y los datos del usuario para conectarse
-
Crea un nuevo proyecto usando Spring Initilizr y agrega las dependencias de Spring Web, Lombok, Spring Data JPA y MySQL Driver.
-
Crea la siguiente estructura de paquetes:
-
Crea una clase
Etapa
y coloca las anotaciones correspondientes de Lombok y JPA. -
Crea una clase
EtapaDto
y coloca las anotaciones correspondientes de Lombok. -
Crea una interface
EtapaMapper
y decórala con@Mapper(componentModel = "spring")
. -
Crea una clase
EtapaRepository
que extienda deJpaRepository
. -
Crea una clase que implemente
CommandLineRunner
y almacena las mismas etapas que en el ejemplo anterior, pero usando los elementos creados en los puntos antiores. Al final debes construir unaEtapaDto
usando un métodobuilder
, convertirlo a unEtapa
usando un mapper de MapStruct y guardarlo en base de datos.
Solución
-
Entra al sitio de Spring Initializr. Ahí verás una sola página dividida en dos secciones. Comienza llenando la información de la sección del lado izquierdo. Selecciona:
-
En la ventana que se abre selecciona las siguientes opciones:
- Grupo, artefacto y nombre del proyecto.
- Tipo de proyecto: Maven Project.
- Lenguaje: Java.
- Forma de empaquetar la aplicación: jar.
- Versión de Java: 11 o 17.
-
En la sección de la derecha (las dependencias) presiona el botón
Add dependencies
y en la ventana que se abre busca las dependenciasSpring Web
,Lombok
,Spring Data JPA
yMySQL Driver
. -
Dale un nombre y una ubicación al proyecto y presiona el botón Generate.
-
En el proyecto que se acaba de crear debes tener el siguiente paquete
org.bedu.java.backend.sesion6.reto2
. Dentro crea los subpaquetes mencionados en las instucciones. -
Agrega al proyecto, en el archivo
pom.xml
las dependencias de MapStruct (las de Lombok se agregaron al momento de crear el proyecto):<properties> <java.version>11</java.version> <org.mapstruct.version>1.4.1.Final</org.mapstruct.version> </properties> <dependencies> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>${org.mapstruct.version}</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> <optional>true</optional> </dependency> </dependencies>
-
Agrega el plugin de Maven para MapStruct, el cual se encargará de generar el código para realizar el mapeo correspondiente.
<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <annotationProcessorPaths> <path> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>${org.mapstruct.version}</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.16</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok-mapstruct-binding</artifactId> <version>0.1.0</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>
-
Dentro del paquete
model
crea una clase llamadaEtapa
con los siguientes atributos:private Long etapaId; private String nombre; private Integer orden;
-
Decora la clase con la anotación
@Data
de Lombok:@Data public class Etapa { }
-
Decora también la clase con las siguientes anotaciones de JPA:
@Data @Entity @Table(name = "ETAPAS") public class Etapa { }
-
Decora los atributos con las siguientes de JPA:
@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long etapaId; @Column(nullable = false, length = 100) private String nombre; @Column(nullable = false, unique = true) private Integer orden;
-
En el paquete
dtos
crea una claseEtapaDto
con los siguientes atributos:private Long etapaId; private String nombre; private Integer orden;
-
Decora esta clase con las anotaciones
@Builder
y@Data
de Lombok.@Builder @Data public class EtapaDto { private Long etapaId; private String nombre; private Integer orden; }
-
En el paquete
persistence
crea una interface llamadaEtapaRepository
que extienda deJpaRepository
. Esta interface permanecerá sin métodos:public interface EtapaRepository extends JpaRepository<Etapa, Long> { }
-
Coloca el siguiente contenido en el archivo
application.properties
(los valores entre los signos<
y>
reemplazalos con tus propios valores):spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.generate_statistics=true spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/bedu?serverTimezone=UTC spring.datasource.username=<usuario> spring.datasource.password=<password>
-
En el paquete
mappers
crea una interfaceEtapaMapper
y decórala con la anotación@Mapper
de MapStruct:@Mapper(componentModel = "spring") public interface EtapaMapper { }
-
Agrega los métodos para convertir de
EtapaDto
aEtapa
y viceversa:@Mapper(componentModel = "spring") public interface EtapaMapper { Etapa etapaDtoToEtapa(EtapaDto etapaDto); EtapaDto etapatoEtapaDto(Etapa etapa); }
-
En el paquete
runners
crea una nueva clase llamadaEtapasVentaRunner
que implemente la interfaceCommandLineRunner
. Decora esta clase con la anotación@Component
de Spring.@Component public class EtapasVentaRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { } }
-
Declara un atributo final de tipo
EtapaRepository
y decora la clase con@RequiredArgsConstructor
:@RequiredArgsConstructor @Component public class EtapasVentaRunner implements CommandLineRunner { private final EtapaRepository etapaRepository; @Override public void run(String... args) throws Exception { } }
-
Declara un atributo de tipo
EtapaMapper
y usa el métodoMappers.getMapper
para obtener el Mapper correspondiente (esto sólo debes hacerlo dentro de unCommandLineRunner
):private EtapaMapper etapaMapper = Mappers.getMapper(EtapaMapper.class);
-
Dentro del método
run
crea un grupo de objetos de tipoEtapa
y guárdalos en la base de datos usando la instancia deetapaRepository
.@RequiredArgsConstructor @Component public class EtapasVentaRunner implements CommandLineRunner { private final EtapaRepository etapaRepository; private EtapaMapper etapaMapper = Mappers.getMapper(EtapaMapper.class); @Override public void run(String... args) throws Exception { Etapa etapa1 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("En espera").orden(0).build()); Etapa etapa2 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Reunión de exploración").orden(1).build()); Etapa etapa3 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Metas establecidas").orden(2).build()); Etapa etapa4 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Plan de acción presentado").orden(3).build()); Etapa etapa5 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Contrato firmado").orden(4).build()); Etapa etapa6 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Venta ganada").orden(5).build()); Etapa etapa7 = etapaMapper.etapaDtoToEtapa(EtapaDto.builder().nombre("Venta perdida").orden(6).build()); List<Etapa> etapas = Arrays.asList(etapa1, etapa2, etapa3, etapa4, etapa5, etapa6, etapa7); etapaRepository.saveAll(etapas); } }
-
Ejecuta la aplicación. No debería haber ningún error en la consola y la aplicación debe iniciar de forma correcta.
-
La base de datos debe estar inicializada con las Etapas: