CodeGym /Cursos /Módulo 5. Spring /Anotaciones JPA: la magia de @Entity, @Id y @Column

Anotaciones JPA: la magia de @Entity, @Id y @Column

Módulo 5. Spring
Nivel 5 , Lección 2
Disponible

Ya sabemos que Hibernate y Spring Data JPA son unos auténticos aliados para trabajar con bases de datos. Se encargan de toda la rutina, ¿pero cómo lo hacen? Ahora vamos a ver las anotaciones que convierten clases Java normales en entidades completas de base de datos.


Introducción a las anotaciones JPA

¡Olvídate de escribir SQL a mano! Con las anotaciones JPA simplemente le dices a la base de datos: "Fíjate, esta clase Java es una tabla, y sus campos son columnas". Cómodo, ¿no?

Las anotaciones JPA funcionan como traductores inteligentes. Toman tus objetos y le explican a la base de datos cómo convertirlos en tablas y columnas que ella entienda.

Aprender las anotaciones JPA es como aprender un idioma nuevo, pero mucho más fácil. En lugar de escribir consultas SQL complejas, trabajas con objetos Java normales, y JPA se encarga de la traducción al lenguaje de la base de datos. Vamos a desglosarlo.


@Entity — creación de "tabla" a partir de una clase

La anotación @Entity es el punto de partida. Le dice al ORM (por ejemplo, Hibernate), que esa clase representa una tabla en la base de datos. Por ejemplo:


import jakarta.persistence.Entity;

@Entity
public class User {
    private Long id;
    private String name;
    private String email;
}

Con @Entity, Hibernate entiende que la clase User corresponde a una tabla en la base de datos. Es como decir: "Oye, Hibernate, aquí tienes mi tabla, trabaja con ella".

Puntos clave:

  • Si no marcas la clase con @Entity, Hibernate no la incluirá en el proceso ORM. Es decir, la base de datos ni siquiera sabrá que existe esa "tabla".
  • Por defecto el nombre de la tabla coincide con el nombre de la clase. Sin embargo, puedes cambiarlo, como veremos más adelante.

Error frecuente: si olvidas añadir @Entity, Hibernate simplemente ignorará tu clase, y te romperás la cabeza preguntándote por qué no se crea la tabla.


@Table — configurar el nombre de la tabla

Aunque por defecto el nombre de la tabla coincide con el nombre de la clase, a veces esto no es conveniente. Por ejemplo, en la base de datos ya existe una tabla con otro nombre. La anotación @Table ayuda a ajustar el nombre de la tabla.


import jakarta.persistence.Entity;
import jakarta.persistence.Table;

@Entity
@Table(name = "users")
public class User {
    private Long id;
    private String name;
    private String email;
}

Ahora Hibernate creará o asociará la entidad con la tabla users, en lugar de User.

Ajustes adicionales de @Table:

  • schema: indica el esquema de la base de datos.
  • catalog: indica el catálogo de la base de datos.
  • uniqueConstraints: permite definir restricciones únicas a nivel de tabla.

Usaremos esta anotación menos a menudo, pero saber configurarla es útil.


@Id — identificador de la tabla

Cada tabla necesita una clave primaria (primary key), para diferenciar las filas. En JPA para esto se usa la anotación @Id. Marca el campo como identificador de la entidad.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class User {

    @Id
    private Long id;

    private String name;
    private String email;
}

Ahora Hibernate sabe que el campo id en nuestra clase — es la clave primaria.

Error frecuente: Si olvidas añadir @Id, Hibernate lanzará una excepción en tiempo de ejecución, porque no podrá generar las órdenes SQL necesarias para operar con la tabla.


@GeneratedValue — generación de identificadores

A menudo los valores de las claves primarias se generan automáticamente (por ejemplo, auto-increment en MySQL). En JPA esto se puede configurar con @GeneratedValue.


import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

@Entity
public class User {

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

    private String name;
    private String email;
}

Formas de generación:

  • GenerationType.IDENTITY: usa auto-increment.
  • GenerationType.SEQUENCE: usa SQL-sequence (especialmente útil en PostgreSQL).
  • GenerationType.TABLE: generación de claves a través de una tabla especial.
  • GenerationType.AUTO: Hibernate decidirá por ti (normalmente usa SEQUENCE o IDENTITY).

Error típico: Si eliges GenerationType.IDENTITY en una base de datos sin auto-increment, obtendrás un error en tiempo de ejecución. Asegúrate de que tu base de datos soporte la estrategia seleccionada.


@Column — configurar columnas

Para mapear un campo de la clase a una columna de la tabla se usa @Column. Por defecto el nombre de la columna coincide con el del campo, pero @Column permite cambiarlo.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Column;

@Entity
public class User {

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

    @Column(name = "full_name", nullable = false, length = 50)
    private String name;

    @Column(unique = true)
    private String email;
}

Parámetros de @Column:

  • name: nombre de la columna en la tabla.
  • nullable: determina si la columna puede contener NULL.
  • unique: establece una restricción UNIQUE.
  • length: longitud máxima de la cadena.

Ahora la columna name en la tabla se llamará full_name, no podrá estar vacía y tendrá una longitud máxima de 50 caracteres.

Error típico: Si la longitud de la cadena excede el valor indicado en length, recibirás una excepción. Además, cambiar los parámetros de la anotación no siempre actualiza automáticamente el esquema de la tabla. ¡No olvides sincronizar los cambios!


@Transient — excluir un campo del mapeo

Cuando tu campo no debe persistirse en la base de datos, puedes marcarlo con @Transient. Esto es útil para datos calculados o temporales.


import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Transient;

@Entity
public class User {

    @Id
    private Long id;

    private String name;

    @Transient
    private String temporaryToken; // No se guarda en la base
}

El campo temporaryToken existirá solo en el objeto User en Java. En la tabla de la base de datos no tendrá ninguna columna correspondiente.


Ejercicio práctico

Tarea: crear la entidad Product con la configuración de la tabla y las columnas.

  1. Crea la entidad Product con los campos:
    • id — clave primaria, auto-increment.
    • name — String, no puede estar vacío.
    • price — número, debe ser mayor que cero.
    • description — texto, se permite NULL.
  2. Configura la tabla con el nombre products.
  3. Configura la columna name con longitud máxima de 100 caracteres.

Ejemplo de solución:


import jakarta.persistence.*;

@Entity
@Table(name = "products")
public class Product {

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

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

    @Column(nullable = false)
    private Double price;

    @Column
    private String description;

    // Getters y setters
}

Resumen

Hoy has aprendido cómo las anotaciones JPA convierten tus clases Java en tablas de base de datos. Has configurado identificadores con @Id y @GeneratedValue, gestionado columnas con @Column, aprendido a excluir campos del mapeo con @Transient, y hasta configurado el nombre de la tabla usando @Table.

Recuerda: es más fácil equivocarse con una anotación de lo que parece, pero Hibernate siempre dará un error claro. Lo importante — no entrar en pánico. 😄

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION