Luis Brandon Flores González
Luis Gerardo Lopez Perez
Hinder Adrian Alvarez Perlaza
¿Cómo crear entidades en Java para mapear tablas de bases de datos?
En esta sección, te guiaré para crear entidades en Java utilizando JPA (Java Persistence API) y mapearlas a las tablas de tu base de datos. Este proceso es esencial para gestionar bases de datos en aplicaciones Java de manera eficiente.
¿Qué son los entities y cómo se crean?
Los entities o entidades son clases en Java que mapean una tabla de una base de datos mediante anotaciones de JPA. Aquí te indico cómo crear una entidad para una tabla llamada "productos":
Crear una Clase Java: Dentro del paquete Per SystemsEntity, inicia una nueva clase Java llamada Producto para mapear la tabla "productos". Utiliza nombres en singular para las clases.
Añadir Anotaciones JPA:
@Entity para indicar que la clase representa una entidad.@Table con el atributo name para definir el nombre real de la tabla.@Entity @Table(name = "productos") public class Producto { // atributos y métodos }
¿Cómo definir los atributos de una entidad?
Para mapear cada columna de la tabla, se definen atributos en la clase que corresponden a las columnas de la tabla:
Atributo para la Clave Primaria: Define un atributo para la clave primaria utilizando tipos de datos empaquetados en Java (p.ej., Integer en lugar de int).
Anotaciones para la Clave Primaria:
@Id para designar el campo como clave primaria.@GeneratedValue(strategy = GenerationType.IDENTITY) si la clave primaria se genera automáticamente.@Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer idProducto;
Resto de Atributos:
String para texto y Double para valores numéricos decimal.@Column con el atributo name.@Column(name = "nombre") private String nombre; @Column(name = "precio_venta") private Double precioVenta;
¿Cómo se generan métodos getter y setter automáticamente?
Java te permite generar automáticamente los métodos getter y setter, lo que facilita la encapsulación y el acceso controlado a los atributos dentro de tus clases.
Accede al menú de generación de código, selecciona la opción para crear getters y setters, y elige todos los atributos de la clase.
public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; }
¿Cómo crear una entidad para la clase compra?
El proceso para crear una entidad para otra tabla, como "compras", sigue pasos similares con pequeñas variaciones según la estructura de la tabla:
Define la Clase y Añade Anotaciones:
@Entity y @Table como se explicó anteriormente.Atributos y Anotaciones:
@Entity @Table(name = "compras") public class Compra { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer idCompra; @Column(name = "id_cliente") private String idCliente; private LocalDateTime fecha; @Column(name = "medio_pago") private String medioPago; }
¿Cómo abordar entidades con claves primarias compuestas?
El manejo de claves primarias compuestas implica conocer cómo definir estas entidades, que será explorado en lecciones futuras. Te animo a que, como ejercicio, intentes crear las entidades para la tabla de "categoría" y "cliente". Recuerda, especialmente para "cliente", no es necesario generar automáticamente la clave primaria si es un dato preexistente y único como un número de cédula.
Al seguir estos pasos y entender las anotaciones, podrás construir un modelo de datos robusto y eficiente para tu aplicación Java, reforzando la conexión y manipulación de datos de manera efectiva. ¡Continúa explorando y aprendiendo para convertirte en un experto en desarrollo Java!
Luis Brandon Flores González
Luis Gerardo Lopez Perez
Hinder Adrian Alvarez Perlaza
Fernando Alfaro
Esteban Salcedo Alvarez
Gloria Peralta Villasante
Gaiserick Jhonatan Ortiz Ramírez
Dualwer Gómez
Gaiserick Jhonatan Ortiz Ramírez
Dianela Tamayo
Alejandro Ramírez
ProfesorCristian Felipe Patiño Cáceres
Diyer Alexander Moreno Hernandez
Reinaldo Mendoza
Daniel Alessandro García Batres
DIEGO ARMANDO CASTELLANOS
Hinder Adrian Alvarez Perlaza
Rolando Mamani Salas
Helí Fernando Jerez Rincón
Ulises Moralez
Helí Fernando Jerez Rincón
José Darío Bedoya Ortiz
Nestor Perez
Cristhian David Gallo Medina
Rafael Uriel Zaldivar
Carl Gaviria
Jose Luis Campos Bautista
Nestor Perez
Marco Antonio Alvarado Cabrera
Alejandro Ramírez
ProfesorMarco Antonio Alvarado Cabrera
Ricardo Mesa Gallego
Borys Jair Castillo Palacios
Alexandra Gomez Huertas
Alejandro Ramírez
ProfesorAlexandra Gomez Huertas
Carlos Alberto Moreno Cifuentes
David German LLicahua Huamani
Helí Fernando Jerez Rincón
Alejandro Ramírez
ProfesorHinder Adrian Alvarez Perlaza
Alejandro Ramírez
ProfesorAlejandro Ramírez
ProfesorMagdiel Linares
Deivy A. Galeano S.
Josué Eliezer Gómez Soto
Elvis Rafael Perez Gutierrez
Daniel Felipe Hernandez Parra
Luis Gomero
Rolando Mamani Salas
Vengo del futuro, el nombrado de las variables/clases en español tiene su propósito. No intenten implementar esta parte en Ingles.
que agradable sujeto
Jajaja presiento que esta declaración merece debate extendido por lo que dure este curso habilitado.
Quisiera dar una mencion aca, desde mi perspectiva, aunque en la clase se usa el tipo Integer para los identificadores o ids, a la larga este tipo de dato no es sustentable, por eso recomiendo el uso del tipo Long.
un apunte muy importante, gracias Fernando.
confirmo afirmo reafirmo
Con la libería Lombok podemos generar automáticamente los getters y setters usando anotaciones y así ahorrarnos mucho código.
Para incluirla debemos añadir esta dependencia en gradle:
compile 'org.projectlombok:lombok:1.18.12'
y ya solo bastaría agregar las anotaciones en la clase para generar los getters y setters
@Getter @Setter @Entity @Table(name = "products") public class Product { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private Long categoryId; private String sku; private Double price; private Integer stock; private boolean status; }
Si ponemos @Getter y @Setter a nivel de clase, se generarán getters y setters para todas sus propiedades. Si queremos getters y setters para sólo una propiedad basta con poner las anotaciones arriba de la propiedad.
Creo saber la razón por la que no se usó lombok para generar los getters and setters. Los mappers de mapstruct (clases más adelante) no funcionan.
Añadiendo el procesador de anotaciones de lombok en el build.gradle lo soluciona
compileOnly 'org.projectlombok:lombok:1.18.12' annotationProcessor 'org.projectlombok:lombok:1.18.2' compileOnly 'org.mapstruct:mapstruct:1.4.0.Final' annotationProcessor 'org.mapstruct:mapstruct processor:1.4.0.Final'
no es buena practica en los imports hacer .*
el ide despues de 4 lo hará automaticamente pero se puede cambiar la propiedad del ide para que automaticamente agregue todo el paquete despúes de 1000 o cualquier número alto
Gran recomendación, Daniela. Gracias!
Hola Daniela gracias por tu aporte, sabes donde puedo configurar esto?
De todos los cursos de JAVA en Platzi, ha sido el mejor profesor como va explicando todo mientras lo va haciendo!
Concuerdo
👏👏👏
Hay una libreria que se llama Lombok que nos ayuda a ahorrar codigo, esta libreria genera los get y los set de manera automatica.
Yo usé la anotación @Data de Lombok para generar los getters y setters. De veras que le ayuda a uno esa anotación.
Muchas gracias ya vi como funciona muchas gracias
Categoria
package com.platzi.market.persistence.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "categorias") public class Category { @Id @Column(name = "id_categoria") @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "description") private String description; @Column(name = "estado") private Boolean active; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public Boolean getActive() { return active; } public void setActive(Boolean active) { this.active = active; } }
Cliente
package com.platzi.market.persistence.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "clientes") public class Client { @Id private String id; @Column(name = "nombre") private String firtsName; @Column(name = "apellidos") private String lastName; @Column(name = "celular") private Long cellphone; @Column(name = "direccion") private String address; @Column(name = "correo_electronico") private String email; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getFirtsName() { return firtsName; } public void setFirtsName(String firtsName) { this.firtsName = firtsName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Long getCellphone() { return cellphone; } public void setCellphone(Long cellphone) { this.cellphone = cellphone; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }
Por qué en la clase Categorías en el atributo description usaste la anotación @Column si no varía el nombre de la columna al que pusiste en el código?
No pasa nada si colocas el @Column, aunque en este caso fue un error de tipado de vscode era descripcion y me lo reemplazo por description.
@Column(name = "descripcion") private String description;
Hola, veo que ya java ha cambiado el nombre de sus libreria al usar la Open jdk 17, la inclusión de clases sale así con jakarta:
import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import jakarta.persistence.Table;
jakarta (Jakarta EE): A partir de Jakarta EE 9 y versiones posteriores, la plataforma empresarial Java se conoce como Jakarta EE. En un esfuerzo por resolver los problemas de licencia y gobernanza, las clases y las API se movieron del paquete javax al paquete jakarta. Por lo tanto, en Jakarta EE 9 y versiones posteriores, encontrarás clases y API en paquetes como jakarta.servlet en lugar de javax.servlet.
Vengo también del futuro. Cuando estén mapeando la clase "Cliente", tengan cuidado al definir al atributo "id". Este debe ser de tipo "String". No cometan el error de declararlo como un tipo Integer, ya que este error es común y es el causante de varios errores en etapas posteriores.
Yo tengo una duda por que lo pusieron asi? No se supone que una busqueda en la BD por medio de strings es mas pesada que usar solo Integers
Tengo entendido que es una buena practica, dejar como tipo de dato cadena (direccion, nit, id, cel), por que son datos con los que no se van a realizar operaciones
Me gusta usar el proyecto Lombok para no escribir los getters y setters.
Yo use Eclipse, y en la pantalla del código, di click derecho, Source > Generate Getters and Setters.
y listo se escribio en automatico.
Saludos.
¿Alguien me puede explicar esto? No lo entendí bien :(
El cliente ya tiene su clave primaria definida y no necesitamos generarla
Cuando digo "El cliente ya tiene su clave primaria definida, no necesitamos generarla automáticamente", me refiero a que NO debemos anotar el campo id de Cliente con @GeneratedValue porque la clave primaria no la define la base datos sino que lo hace directamente nuestra aplicación porque debemos recibir el número de identificación del cliente al crearlo.
¿Alguien instalo lombok? Digo... para no tener que estar generando los gets y sets
Si señor! Muy util para ahorrarnos codigo y que sea mas limpio todo
Hello guys, I’m going to share my way how I solved this challenge, have a look. I used lombook dependency to avoid generating getters and setters methods, In my point of view our entities looks better. https://github.com/borisbikes/platzi/tree/main/Spring/platzi-market/src/main/java/com/platzi/market/persistence/entity
Por que es mejor usar Integer que INT ??
Gran respuesta @ivancarrenocalzada! 👏
Mil gracias @ivancarrenocalzado por tu detallada respuesta, quedo claro.
Para quien esté haciendo este curso en estos días, y con un JDK igual superior a Java 17, no se asusten si la anotación @Entity se carga desde jakarta.persistence... es normal (las dependencias de javax para persistencia, si mal no estoy, fue absorbida por jakarta)
Cual es la diferencia entre usar GenerationType.IDENTITY y GenerationType.SEQUENCE?
La diferencia esta en que JPA cuando ud haga save:
Como bien menciona Fernando, cuando usas GenerationType.IDENTITY la base de datos se encarga de auto-incrementar el valor cada que hace un INSERT. Por su parte, GenerationType.SEQUENCE ejecuta una sentencia SELECT para verificar el valor de la secuencia (este proceso no tiene impacto en el rendimiento de la aplicación) y luego se le asigna al entity. Te dejo este video donde explican a detalle las características y comparaciones entre las diferentes estrategias.
Pregunta: ¿los campos ++medio_pago++ y ++estado++ por qué no se declararon de tipo Character si en BD están de tipo character y se le puso de tipo String en el entity?
La verdad no lo pensé mucho y quizás fue por mera practicidad; para ser fieles al mapeo debí haber usado el Character. Para el controller es indiferente porque desde el JSON no puedo indicarle que es solo un carácter y siempre tendré que ponerlo entre comillas dobles (cuando lo recibe entenderá como String).
Modifiqué el código para cambiar por Character e hice las respectivas pruebas y sigue funcionando sin problemas.
Solo para comprobar, usé un JPA Tools que me permite crear los entities automáticamente desde las tablas y utiliza String en lugar de Character 🤷♂️
Para resumir: Debí usar Character pero no existe ningún problema (ni de memoria) con String.
Uno de los principales cambios en SpringBoot 3.1 es que las anotaciones JPA ahora son importadas del paquete jakarta y no javax, ya que tiene como base a Jakarta EE 9:
import jakarta.persistence.Entity;
gracias!! me tuvo buscando un buen rato
Gracias estaba buscando sobre ello...
Este es mi codigo
categorias
package com.platzi.market.persistence.entity; import javax.persistence.*; @Entity @Table(name = "categorias") public class Categoria { @Column(name = "id_categoria" ) @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer idCategoria; private String descripcion; private Boolean estado; public Integer getIdCategoria() { return idCategoria; } public void setIdCategoria(Integer idCategoria) { this.idCategoria = idCategoria; } public String getDescripcion() { return descripcion; } public void setDescripcion(String descripcion) { this.descripcion = descripcion; } public Boolean getEstado() { return estado; } public void setEstado(Boolean estado) { this.estado = estado; } }
Cliente
package com.platzi.market.persistence.entity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "clientes") public class Cliente { @Id private String id; private String nombre; private String apellidos; private Integer celular; private String direccion; @Column(name = "correo_electronico") private String correoElectronico; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public Integer getCelular() { return celular; } public void setCelular(Integer celular) { this.celular = celular; } public String getDireccion() { return direccion; } public void setDireccion(String direccion) { this.direccion = direccion; } public String getCorreoElectronico() { return correoElectronico; } public void setCorreoElectronico(String correoElectronico) { this.correoElectronico = correoElectronico; } }
no puedes dejar celular como integer, dado a su cantidad de números
Yo suelo usar estas anotaciones en mis proyectos, se las recomiendo:
@Entity @Table(name = "productos") @AllArgsConstructor @NoArgsConstructor @Getter @Setter @SuperBuilder public class Producto { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id_producto") private Integer idProducto; private String nombre; @Column(name = "id_categoria") private Integer idCategoria; @Column(name = "codigo_barras") private String codigoBarras; @Column(name = "precio_venta") private Double precioVenta; @Column(name = "cantidad_stock") private Integer cantidadStock; private Boolean estado; }
Muchas Gracias