Hibernate

Hibernate

Tutorial Hibernate: Creación de entidades JPA

Spring Boot entidades JPA: mapeo y gestión. Domina el mapeo y gestión de entidades JPA en Spring Boot con ejemplos prácticos.

Introducción

JPA es una especificación estándar de Java para la persistencia de objetos en bases de datos relacionales. En lugar de escribir consultas SQL directamente, los desarrolladores pueden trabajar con clases y objetos Java y dejar que JPA se encargue de convertir esos objetos en registros de la base de datos y viceversa.

Las entidades JPA son, por tanto, el núcleo de esta solución. Son clases Java que representan tablas en la base de datos. Una entidad puede representar a un "Usuario", un "Pedido", un "Producto" o cualquier otra entidad de negocio que necesite ser almacenada y recuperada de una base de datos.

Estas entidades facilitan no solo la representación de la estructura de la base de datos en el código, sino también la manipulación de los datos. Las operaciones CRUD (Crear, Leer, Actualizar, Eliminar) se vuelven más intuitivas, ya que se realizan sobre objetos, y JPA se encarga de transformar estas operaciones en las correspondientes consultas SQL.

Por último, es importante destacar que JPA no es una implementación en sí misma, sino una especificación. Existen varias implementaciones de JPA, siendo Hibernate una de las más populares y ampliamente utilizadas en la industria.

Anotación @Entity

La anotación @Entity juega un papel fundamental en JPA, ya que marca una clase Java como una entidad, es decir, como una representación de una tabla en una base de datos relacional. Pero, ¿qué implica exactamente esta marca y qué características y comportamientos lleva consigo? Veamos más en detalle:

Definición

Una entidad JPA es una clase ligera de POJO (Plain Old Java Object) que está vinculada a una tabla específica en la base de datos. La anotación @Entity le indica al proveedor JPA (como Hibernate) que la clase en la que se coloca debe ser tratada como tal entidad. Por lo tanto, la clase se mapeará a una tabla con el mismo nombre que la clase, a menos que se especifique lo contrario.

Requisitos

Para que una clase sea una entidad JPA válida al utilizar la anotación @Entity, debe cumplir con ciertos requisitos:

  1. Debe tener un constructor público sin argumentos (puede tener otros constructores además del predeterminado).
  2. No debe ser final, ya que el proveedor de JPA podría necesitar crear subclases proxy de la entidad.
  3. Debe contener al menos una propiedad o campo con la anotación @Id, que representa la clave primaria de la entidad.

Nomenclatura de la tabla

Por defecto, la tabla a la que se mapeará la entidad tendrá el mismo nombre que la clase Java. Sin embargo, si se desea mapear la entidad a una tabla con un nombre diferente, se puede utilizar la anotación @Table junto con @Entity.

Por ejemplo:

import jakarta.persistence.*;

@Entity
@Table(name="usuarios")
public class Usuario {
    // campos y métodos
}

En el ejemplo anterior, aunque la clase se llama Usuario, los datos de esta entidad se guardarán en una tabla llamada "usuarios".

Persistencia y ciclo de vida

Una vez que una clase ha sido anotada con @Entity, adquiere un ciclo de vida de persistencia. Las entidades pueden estar en diferentes estados: nuevo (no persistente), gestionado (persistente), separado (anteriormente persistente pero ahora no) y eliminado. Las transiciones entre estos estados son gestionadas por el EntityManager de JPA, lo que permite realizar operaciones como persistir, actualizar, fusionar o eliminar la entidad en relación con la base de datos subyacente.

Anotación @Id

La anotación @Id es esencial en el contexto de las entidades JPA porque indica qué atributo o campo de la clase se utiliza como clave primaria en la tabla de la base de datos correspondiente. La clave primaria es vital en el modelo relacional, ya que garantiza la unicidad de cada registro y permite realizar referencias eficientes entre tablas.

Significado

La anotación @Id se coloca justo antes de la declaración del atributo que se desea usar como clave primaria. Este atributo puede ser de varios tipos, como int, long, String, etc., dependiendo de las necesidades y el diseño de la base de datos.

Ejemplo básico

import jakarta.persistence.*;

@Entity
public class Libro {
    
    @Id
    private Long isbn;
    
    // Otros campos y métodos
}

En este ejemplo, isbn es la clave primaria de la entidad Libro.

Características clave

  1. Unicidad: La clave primaria de una entidad garantiza la unicidad. Esto significa que no puede haber dos entidades de la misma clase con el mismo valor de clave primaria en la base de datos.
  2. Inmutabilidad: Una vez que una entidad ha sido persistida (guardada) en la base de datos, su clave primaria no debe cambiar. Modificar el valor de una clave primaria ya persistida puede llevar a un comportamiento indeseado o errores.
  3. No nulos: Las claves primarias no deben ser null. Es importante asegurarse de que el atributo anotado con @Id siempre tenga un valor antes de persistir la entidad.

Colocación de @Id

Aunque en la mayoría de los casos se coloca @Id sobre un campo, también es posible colocarlo sobre un método getter del campo que se desea utilizar como clave primaria. Esta es una cuestión de estilo y de cómo se desea diseñar la clase, pero el resultado funcional es el mismo.

Uso junto con @GeneratedValue

A menudo, la anotación @Id se usa junto con la anotación @GeneratedValue, que indica que el valor de la clave primaria debe ser generado automáticamente. Esto es común en escenarios donde se desea que la base de datos genere un valor único automáticamente, como un ID autoincrementable.

import jakarta.persistence.*;
@Entity
public class Estudiante {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // Otros campos y métodos
}

En este caso, la base de datos generará automáticamente un valor único para el campo id cada vez que se persista una nueva entidad Estudiante.

Anotación @GeneratedValue

La anotación @GeneratedValue en el contexto de JPA se utiliza para indicar que un valor se generará automáticamente para un campo o propiedad. Es especialmente útil para claves primarias, permitiendo que estas se creen de forma automática cada vez que se inserta una nueva entidad en la base de datos. Vamos a examinar más detalladamente esta anotación y sus características.

Estrategias de Generación

La principal característica de @GeneratedValue es la definición de la estrategia de generación de valor. JPA ofrece varias estrategias para adaptarse a diferentes necesidades y bases de datos:

AUTO: Esta es la estrategia predeterminada. Deja que el proveedor de persistencia elija la estrategia que mejor se adapte a la base de datos particular. El proveedor puede elegir entre SEQUENCE, IDENTITY o TABLE según la base de datos.

IDENTITY: Esta estrategia se basa en columnas autoincrementables de la base de datos. Cuando se inserta una nueva entidad, la base de datos generará automáticamente un nuevo valor para la columna. Es común en bases de datos como MySQL.

SEQUENCE: Utiliza secuencias de bases de datos para generar valores. Es eficiente y es una opción popular en bases de datos que admiten secuencias, como Oracle o PostgreSQL. Si se elige esta estrategia, se puede usar la anotación @SequenceGenerator para proporcionar detalles adicionales sobre la secuencia, como su nombre o el valor inicial.

TABLE: Esta estrategia utiliza una tabla específica en la base de datos para generar valores. Cada fila en esta tabla representa un generador de valores. Aunque es la estrategia menos eficiente, tiene la ventaja de ser portable entre diferentes bases de datos. Si se utiliza esta estrategia, se puede emplear la anotación @TableGenerator para configurar detalles específicos de la tabla.

UUID: indica que el proveedor de persistencia debe asignar claves primarias para la entidad generando un identificador único universal RFC 4122. 

Ejemplo de uso

import jakarta.persistence.*;

@Entity
public class Empleado {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    // Otros campos y métodos
}

En el ejemplo anterior, el campo id se genera automáticamente utilizando la estrategia IDENTITY.

Consideraciones

Es importante elegir la estrategia adecuada según el tipo de base de datos y las necesidades específicas de la aplicación. Por ejemplo, la estrategia IDENTITY podría no ser la mejor opción para bases de datos que no soporten columnas autoincrementables.

Al usar estrategias como SEQUENCE o TABLE, se debe garantizar que la configuración (por ejemplo, nombres de secuencias o tablas) sea consistente con lo que existe en la base de datos.

Aunque @GeneratedValue es comúnmente utilizado con claves primarias, técnicamente puede ser utilizado con cualquier campo o propiedad que se quiera generar automáticamente. Sin embargo, en la práctica, su uso más común y recomendado es con claves primarias.

Otros aspectos a considerar

Más allá de las anotaciones básicas como @Entity, @Id y @GeneratedValue, hay muchos otros aspectos y características en JPA que los desarrolladores deben considerar para modelar y trabajar eficazmente con entidades. Estas características pueden abordar diferentes problemáticas o necesidades en el mapeo objeto-relacional. Vamos a profundizar en algunos de estos aspectos:

Anotación @Column

Permite especificar detalles sobre la columna a la que se mapea un campo o propiedad en particular.

@Column(name="nombre_completo", nullable=false, length=200)
private String nombre;

En este ejemplo, el atributo nombre se mapea a la columna "nombre_completo" en la base de datos, no permite valores nulos y tiene una longitud máxima de 200 caracteres.

Relaciones entre entidades

JPA proporciona anotaciones para representar relaciones entre entidades, reflejando las relaciones típicas de las bases de datos relacionales:

  • @OneToOne: Para relaciones uno a uno.
  • @OneToMany y @ManyToOne: Para relaciones uno a muchos y muchos a uno, respectivamente.
  • @ManyToMany: Para relaciones muchos a muchos.

Por ejemplo:

@Entity
public class Autor {
    @OneToMany(mappedBy="autor")
    private List<Libro> libros;
}

Anotación @Transient

Los campos marcados con esta anotación no se persisten, es decir, no se guardan en la base de datos. Es útil para campos que contienen datos derivados o temporales que no necesitan ser almacenados.

@Transient
private String informacionTemporal;

Anotación @Enumerated

Se utiliza para mapear atributos enum a columnas de base de datos. Puede almacenarse como un nombre de String (por defecto) o como un int.

@Enumerated(EnumType.STRING)
private TipoUsuario tipo;

Conversores (@Converter y @Convert)

Los conversores permiten transformar atributos de entidad antes de persistirlos y después de recuperarlos. Son útiles para casos en los que se necesita almacenar un tipo de dato de una manera específica en la base de datos.

Anotación @Version

Esta anotación se utiliza para la gestión optimista de concurrencia. Un campo marcado con @Version se incrementará automáticamente cada vez que una entidad se actualice, permitiendo a JPA detectar conflictos cuando dos o más transacciones intenten actualizar la misma entidad simultáneamente.

@Version
private int version;

Herencia

JPA soporta mapeo de herencia, lo que permite modelar relaciones de herencia entre entidades. Las estrategias de mapeo incluyen SINGLE_TABLE, JOINED, y TABLE_PER_CLASS.

Callbacks y eventos del ciclo de vida

JPA permite definir métodos que se llaman en ciertos puntos del ciclo de vida de una entidad, como antes de persistir (@PrePersist) o después de cargar (@PostLoad).

Certifícate en Hibernate con CertiDevs PLUS

Ejercicios de esta lección Creación de entidades JPA

Evalúa tus conocimientos de esta lección Creación de entidades JPA con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.

Consultas JPQL avanzadas

Hibernate
Código

Configuración con JPA

Hibernate
Test

Tipos de datos personalizados

Hibernate
Puzzle

Consultas Criteria avanzadas

Hibernate
Código

Operaciones en cascada

Hibernate
Test

Anotaciones JPA

Hibernate
Puzzle

Asociación Many To One

Hibernate
Test

Funciones en consultas JPQL

Hibernate
Código

Asociación Many To Many entre Actor y Pelicula

Hibernate
Código

Asociación One To Many entre Curso y Estudiante

Hibernate
Código

Tipos de datos básicos

Hibernate
Test

Consultas Criteria básicas

Hibernate
Código

Asociación Many To Many

Hibernate
Puzzle

CRUD de entidades con asociaciones

Hibernate
Proyecto

Optimización de asociaciones con carga lazy

Hibernate
Código

Asociación One To Many

Hibernate
Puzzle

Configuración con Maven

Hibernate
Test

Asociación One To One

Hibernate
Test

CRUD en Hibernate

Hibernate
Código

Operaciones en cascada

Hibernate
Puzzle

Introducción a Hibernate

Hibernate
Test

Atributos de tipo enum en entidades JPA

Hibernate
Código

Carga de asociaciones en consultas con EntityGraph

Hibernate
Código

Configuración con Gradle

Hibernate
Test

Asociación One To One entre Libro y Resumen

Hibernate
Código

Asociación One To Many

Hibernate
Test

Asociación Many To Many

Hibernate
Test

Creación de entidades

Hibernate
Test

Ciclo de vida de una entidad

Hibernate
Código

Consultas JPQL básicas

Hibernate
Código

Carga de asociaciones en consultas con EntityGraph y anotaciones

Hibernate
Código

Tipos de datos embebidos

Hibernate
Código

Asociación Many To One entre Paciente y Clinica

Hibernate
Código

Asociación Many To One

Hibernate
Puzzle

Optimización de consultas con DTOs

Hibernate
Código

Atributos @Transient en entidades

Hibernate
Código

Asociación One To One

Hibernate
Puzzle

Todas las lecciones de Hibernate

Accede a todas las lecciones de Hibernate y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Introducción A Hibernate

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Gradle

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Maven

Hibernate

Introducción Y Entorno

Configuración Hibernate Con Jpa

Hibernate

Introducción Y Entorno

Creación De Entidades Jpa

Hibernate

Entidades Jpa Y Tipos De Datos

Tipos De Datos En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Atributos @Transient En Entidades

Hibernate

Entidades Jpa Y Tipos De Datos

Enums En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Tipos De Datos Embebidos

Hibernate

Entidades Jpa Y Tipos De Datos

Crud En Hibernate

Hibernate

Entidades Jpa Y Tipos De Datos

Ciclo De Vida De Una Entidad

Hibernate

Entidades Jpa Y Tipos De Datos

Asociación One To One

Hibernate

Asociaciones Entre Entidades

Asociación One To Many

Hibernate

Asociaciones Entre Entidades

Asociación Many To One

Hibernate

Asociaciones Entre Entidades

Asociación Many To Many

Hibernate

Asociaciones Entre Entidades

Operaciones En Cascada

Hibernate

Asociaciones Entre Entidades

Consultas Jpql Básicas

Hibernate

Consultas Hql Y Jpql

Consultas Jpql Avanzadas

Hibernate

Consultas Hql Y Jpql

Funciones En Consultas Jpql

Hibernate

Consultas Hql Y Jpql

Consultas Criteria Básicas

Hibernate

Api Criteria De Jpa

Consultas Criteria Avanzadas

Hibernate

Api Criteria De Jpa

Carga De Asociaciones En Consultas Con Entitygraph

Hibernate

Api Entitygraph

Carga De Asociaciones En Consultas Con Entitygraph Y Anotaciones

Hibernate

Api Entitygraph

Optimización De Consultas Con Dtos

Hibernate

Optimización

Optimización De Asociaciones Con Carga Lazy

Hibernate

Optimización

Certificados de superación de Hibernate

Supera todos los ejercicios de programación del curso de Hibernate y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.

En esta lección

Objetivos de aprendizaje de esta lección

  1. Comprender la relación entre entidades JPA y tablas de bases de datos y cómo estas reflejan el mapeo objeto-relacional.
  2. Aprender a utilizar anotaciones clave como @Entity, @Id, y @GeneratedValue para definir y gestionar entidades.
  3. Familiarizarse con las relaciones entre entidades y cómo se representan en JPA.
  4. Adquirir habilidades para configurar y personalizar el comportamiento de las entidades según las necesidades específicas de la aplicación.
  5. Entender las mejores prácticas para la optimización y gestión del rendimiento con JPA en aplicaciones reales.