Contenido del curso

Spring Data Repositories

Cómo crear entities JPA con Hibernate

Resumen

Crear entities en Spring Boot te permite traducir clases Java en tablas reales dentro de tu base de datos sin escribir SQL manual. Aprenderás a mapear atributos, definir claves primarias y aprovechar Hibernate para que el modelo se genere automáticamente.

Esta guía es para quienes ya conectaron su proyecto Spring Boot a una base de datos y quieren empezar a modelar la capa de persistencia con JPA.

¿Qué es una entity en JPA y cómo se declara?

Una entity es una clase Java que JPA traduce a una tabla relacional. Para declararla necesitas dos anotaciones de Jakarta: @Entity marca la clase como entidad gestionada y @Table(name = "pizza") define el nombre exacto de la tabla en la base de datos.

¿Qué hace la anotación @Entity? Le dice a JPA que esa clase representa una tabla y que debe ser gestionada por el contexto de persistencia. Sin ella, Hibernate ignora la clase.

En el proyecto creas el paquete com.platzi.pizza.persistence.entity y dentro defines una clase llamada PizzaEntity. El nombre de la clase puede diferir del nombre de la tabla; por eso @Table es clave para mantener la convención que prefieras en tu base de datos [01:00].

¿Cómo defino la clave primaria con @Id y @GeneratedValue?

La clave primaria se anota con @Id. Para que el motor genere el valor automáticamente cada vez que insertas un registro, agregas @GeneratedValue(strategy = GenerationType.IDENTITY). Existen otras estrategias como SEQUENCE, AUTO o UUID, pero IDENTITY delega el autoincremento a la base de datos [01:45].

Cuando el nombre del atributo en Java no coincide con el de la columna, usas @Column(name = "id_pizza", nullable = false). Así idPizza en tu clase se mapea a id_pizza en la tabla.

¿Cómo configuro columnas con restricciones de tipo y tamaño?

La anotación @Column admite varios parámetros para reflejar restricciones reales del esquema:

  • nullable = false para impedir valores nulos.
  • length = 30 para limitar la longitud de un string.
  • unique = true para evitar duplicados, como en el nombre de la pizza.
  • columnDefinition = "decimal(5,2)" cuando necesitas un tipo SQL específico que JPA no infiere por defecto.

Para campos booleanos que en MySQL viven como TINYINT, defines private boolean vegetarian y lo acompañas con @Column(columnDefinition = "TINYINT"). Si además es obligatorio, sumas nullable = false [04:30].

¿Cómo modelar la entity Pizza paso a paso?

La tabla pizza tiene siete columnas: identificador, nombre, descripción, precio y tres banderas booleanas. Cada una se traduce así dentro de PizzaEntity:

  • idPizza como Integer, clave primaria con autoincremento.
  • name como String único, no nulo, con longitud 30.
  • description como String no nulo con longitud 150.
  • price como double con columnDefinition = "decimal(5,2)".
  • vegetarian, vegan y available como boolean con TINYINT.

Fíjate que en name y description no necesitas el parámetro name dentro de @Column porque el atributo Java ya coincide con la columna. Solo lo usas cuando hay diferencia, como ocurre con id_pizza por el guion bajo [03:20].

¿Por qué usar @Getter, @Setter y @NoArgsConstructor en lugar de @Data?

Lombok acelera la creación de getters, setters y constructores, pero @Data también genera equals y hashCode automáticamente. Esa es una mala práctica en entidades JPA porque puede romper la igualdad entre objetos gestionados y no gestionados por el contexto de persistencia.

La recomendación es usar tres anotaciones por separado: @Getter, @Setter y @NoArgsConstructor. Así mantienes el control sobre cómo se comparan tus entidades [06:40].

¿Cómo crea Hibernate las tablas automáticamente?

Al ejecutar la aplicación, Hibernate lee tus entities y genera las sentencias CREATE TABLE correspondientes. En consola verás el SQL que produce, incluyendo los constraints únicos y los tipos definidos por columnDefinition.

Gracias a la propiedad spring.jpa.hibernate.ddl-auto, el motor solo crea o actualiza lo que falta. Si la tabla ya existe sin cambios, no la recrea. Esto se nota cuando agregas una segunda entidad: solo se genera la tabla nueva [09:20].

¿Qué diferencia hay entre length y columnDefinition? length controla el tamaño de un varchar, mientras que columnDefinition te permite escribir el tipo SQL exacto, útil para decimal, datetime o tinyint.

¿Cómo modelar la entity Order para órdenes de servicio?

La segunda entidad se llama OrderEntity y mapea la tabla pizza_order. Su estructura usa los mismos principios pero con tipos distintos:

  • idOrder como Integer, clave primaria con IDENTITY.
  • idCustomer como String no nulo, longitud 15.
  • date como LocalDateTime con columnDefinition = "datetime" para guardar fecha y hora.
  • total como double con columnDefinition = "decimal(6,2)".
  • method como String no nulo con columnDefinition = "char(1)" para optimizar memoria.
  • additionalNotes como String con longitud 200, este sí admite nulos.

Usar char(1) en lugar de un varchar(256) por defecto evita reservar espacio innecesario cuando solo guardas un carácter como método de pago [11:50].

¿Cómo verificar que las tablas se crearon correctamente?

Después de reiniciar la aplicación, abres MySQL Workbench, refrescas la conexión y revisas la sección Tables. Allí encontrarás pizza y pizza_order con todas las columnas y restricciones que definiste en código.

Si vuelves a ejecutar el proyecto sin cambios, Hibernate no genera nada nuevo. Esa es la ventaja del ddl-auto: tu esquema evoluciona junto con tus entities.

Ahora viene el reto: crea las entidades para las tablas Customer y OrderItem. Esta última tiene una clave primaria compuesta, así que necesitarás investigar cómo anotarla para que funcione. ¿Cómo resolverías esa clave compuesta? Cuéntame en los comentarios cómo lo abordaste antes de avanzar a la próxima clase.