Hibernate: Entidades JPA

Descubre cómo usar entidades JPA para mapear clases Java a tablas de base de datos con Hibernate y optimiza tus aplicaciones empresariales.

Aprende Hibernate GRATIS y certifícate

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.

Empezar curso de Hibernate

Lecciones de este módulo de Hibernate

Lecciones de programación del módulo Entidades JPA del curso de Hibernate.

Ejercicios de programación en este módulo de Hibernate

Evalúa tus conocimientos en Entidades JPA con ejercicios de programación Entidades JPA de tipo Test, Puzzle, Código y Proyecto con VSCode.