Hibernate: Entidades JPA

Hibernate
Hibernate
Actualizado: 17/06/2025

Entidades JPA

Las entidades JPA constituyen el núcleo fundamental de cualquier aplicación que utilice el mapeo objeto-relacional con Hibernate. Una entidad representa una tabla de base de datos como una clase Java, permitiendo que los desarrolladores trabajen con datos relacionales utilizando el paradigma orientado a objetos.

Concepto fundamental de entidades

Una entidad JPA es una clase Java que se mapea directamente a una tabla de base de datos. Cada instancia de la entidad corresponde a una fila en la tabla, mientras que los atributos de la clase representan las columnas. Esta abstracción permite manipular datos relacionales sin escribir SQL directamente.

@Entity
@Table(name = "usuarios")
public class Usuario {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "nombre_usuario")
    private String nombreUsuario;
    
    @Column(nullable = false)
    private String email;
    
    // Constructores, getters y setters
}

El ejemplo anterior muestra una entidad básica que mapea la clase Usuario a la tabla usuarios. La anotación @Entity marca la clase como una entidad JPA, mientras que @Table especifica el nombre de la tabla en la base de datos.

Anotaciones esenciales para entidades

Identificación de entidades

Toda entidad debe tener un identificador único marcado con @Id. Este identificador representa la clave primaria de la tabla:

@Entity
public class Producto {
    @Id
    private String codigo;
    
    private String nombre;
    private BigDecimal precio;
}

Para claves primarias autogeneradas, se utiliza @GeneratedValue con diferentes estrategias:

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

Mapeo de columnas

La anotación @Column permite personalizar cómo se mapean los atributos a las columnas de la base de datos:

@Entity
public class Cliente {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "nombre_completo", length = 100, nullable = false)
    private String nombre;
    
    @Column(unique = true)
    private String dni;
    
    @Column(precision = 10, scale = 2)
    private BigDecimal saldo;
}

Tipos de datos y mapeo

Hibernate mapea automáticamente los tipos básicos de Java a sus equivalentes SQL. Los tipos primitivos y sus wrappers, String, Date, y BigDecimal se mapean sin configuración adicional:

@Entity
public class Evento {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String titulo;
    private LocalDateTime fechaInicio;
    private LocalDateTime fechaFin;
    private boolean activo;
    private int capacidadMaxima;
}

Para tipos más complejos, Hibernate proporciona anotaciones específicas:

@Entity
public class Documento {
    @Id
    private String id;
    
    @Lob
    private byte[] contenido;
    
    @Enumerated(EnumType.STRING)
    private TipoDocumento tipo;
    
    @Temporal(TemporalType.TIMESTAMP)
    private Date fechaCreacion;
}

Ciclo de vida de las entidades

Las entidades JPA pasan por diferentes estados durante su ciclo de vida. Comprender estos estados es crucial para trabajar eficazmente con Hibernate:

  • Transient: La entidad existe en memoria pero no está asociada con ningún contexto de persistencia
  • Persistent: La entidad está asociada con un contexto de persistencia y cualquier cambio se sincronizará con la base de datos
  • Detached: La entidad existía en un contexto de persistencia que ya se cerró
  • Removed: La entidad está marcada para eliminación
// Estado Transient
Usuario usuario = new Usuario();
usuario.setNombre("Juan");

// Estado Persistent (después de persist)
entityManager.persist(usuario);

// Estado Detached (después de cerrar el EntityManager)
entityManager.close();

// Estado Removed
entityManager.remove(usuario);

Validaciones y restricciones

Las validaciones Bean Validation se integran perfectamente con las entidades JPA, proporcionando validación tanto a nivel de aplicación como de base de datos:

@Entity
public class Empleado {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @NotBlank
    @Size(min = 2, max = 50)
    private String nombre;
    
    @Email
    @Column(unique = true)
    private String email;
    
    @Min(18)
    @Max(65)
    private int edad;
    
    @DecimalMin("0.0")
    private BigDecimal salario;
}

Configuración avanzada de entidades

Herencia de entidades

Hibernate soporta diferentes estrategias de herencia para mapear jerarquías de clases:

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "tipo_vehiculo")
public abstract class Vehiculo {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String marca;
    private String modelo;
}

@Entity
@DiscriminatorValue("COCHE")
public class Coche extends Vehiculo {
    private int numeroPuertas;
}

@Entity
@DiscriminatorValue("MOTO")
public class Motocicleta extends Vehiculo {
    private int cilindrada;
}

Entidades embebidas

Los objetos embebidos permiten agrupar campos relacionados en una clase separada sin crear una tabla adicional:

@Embeddable
public class Direccion {
    private String calle;
    private String ciudad;
    private String codigoPostal;
    private String pais;
}

@Entity
public class Empresa {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String nombre;
    
    @Embedded
    private Direccion direccion;
    
    @Embedded
    @AttributeOverrides({
        @AttributeOverride(name = "calle", column = @Column(name = "direccion_facturacion_calle")),
        @AttributeOverride(name = "ciudad", column = @Column(name = "direccion_facturacion_ciudad"))
    })
    private Direccion direccionFacturacion;
}

Optimización y rendimiento

Las entidades pueden configurarse para optimizar el rendimiento de las consultas. El lazy loading es fundamental para evitar cargar datos innecesarios:

@Entity
public class Pedido {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @OneToMany(mappedBy = "pedido", fetch = FetchType.LAZY)
    private List<LineaPedido> lineas = new ArrayList<>();
    
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "cliente_id")
    private Cliente cliente;
}

La configuración de caché de segundo nivel mejora significativamente el rendimiento en aplicaciones con patrones de acceso repetitivos:

@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Categoria {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String nombre;
    private String descripcion;
}

Las entidades JPA en Hibernate proporcionan una base sólida para el desarrollo de aplicaciones empresariales, ofreciendo un mapeo objeto-relacional robusto y flexible que se adapta a las necesidades específicas de cada proyecto.

Explora más sobre Hibernate

Descubre más recursos de Hibernate

Alan Sastre - Autor del curso

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Hibernate es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.