Entidades en JPA El Corazón de la Persistencia en Java

Entidades en JPA: El Corazón de la Persistencia en Java

1. Introducción

En este tutorial, aprenderemos sobre los conceptos básicos de las entidades, junto con varias anotaciones que definen y personalizan una entidad en JPA (Java Persistence API). Comprender cómo funcionan las entidades es esencial para cualquier programador Java que desee interactuar con bases de datos de manera efectiva. Vamos a profundizar en cómo crear entidades, cómo configurarlas y cómo utilizar las anotaciones para definir la estructura de nuestros datos.

2. Entidad

Las entidades en JPA son, en esencia, POJOs (Plain Old Java Objects) que representan datos que pueden ser persistidos en la base de datos. Una entidad representa una tabla almacenada en una base de datos, y cada instancia de una entidad representa una fila en esa tabla.

2.1. La Anotación @Entity

Supongamos que tenemos un POJO llamado Student, que representa la información de un estudiante, y queremos almacenarlo en la base de datos. Para que JPA reconozca este POJO como una entidad, debemos definirlo utilizando la anotación @Entity.


@Entity
public class Student {
    // campos, getters y setters
}

Es importante asegurarse de que la entidad tenga un constructor sin argumentos y una clave primaria. Así es como podemos definirlo:


@Entity
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    private String name;

    // getters y setters
}

El nombre de la entidad se establece de forma predeterminada como el nombre de la clase. No obstante, podemos cambiar su nombre utilizando el elemento name:


@Entity(name="student")
public class Student {
    // campos, getters y setters
}

Debido a que diversas implementaciones de JPA intentarán crear subclases de nuestra entidad para ofrecer su funcionalidad, las clases de entidad no deben ser declaradas como final.

2.2. La Anotación @Id

Cada entidad JPA debe tener una clave primaria que la identifique de manera única. La anotación @Id define la clave primaria. Podemos generar los identificadores de diferentes maneras, especificadas por la anotación @GeneratedValue.

Ejemplo de una entidad utilizando @Id:


@Entity
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;
    
    private String name;

    // getters y setters
}

El valor de la estrategia puede ser AUTO, TABLE, SEQUENCE o IDENTITY. Si elegimos GenerationType.AUTO, el proveedor JPA utilizará cualquier estrategia que desee para generar los identificadores.

Si anotamos los campos de la entidad, el proveedor JPA utilizará estos campos para obtener y establecer el estado de la entidad. En adición al acceso por campo, también podemos hacer acceso por propiedad o acceso mixto, que permite usar tanto acceso por campo como por propiedad en la misma entidad.

2.3. La Anotación @Table

En muchos casos, el nombre de la tabla en la base de datos y el nombre de la entidad no serán los mismos. En estos casos, podemos especificar el nombre de la tabla utilizando la anotación @Table:


@Entity
@Table(name="STUDENT")
public class Student {
    // campos, getters y setters
}

También podemos mencionar el esquema utilizando el elemento schema:


@Entity
@Table(name="STUDENT", schema="SCHOOL")
public class Student {
    // campos, getters y setters
}

El nombre del esquema ayuda a distinguir entre conjuntos de tablas. Si no usamos la anotación @Table, el nombre de la tabla será el mismo que el de la entidad.

2.4. La Anotación @Column

Al igual que la anotación @Table, podemos utilizar la anotación @Column para mencionar los detalles de una columna en la tabla.

La anotación @Column tiene muchos elementos como name, length, nullable y unique:


@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

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

    // otros campos, getters y setters
}

El elemento name especifica el nombre de la columna en la tabla, length especifica su longitud, nullable especifica si la columna puede ser nula o no, y unique especifica si la columna es única.

Si no especificamos esta anotación, el nombre de la columna en la tabla será el mismo que el del campo.

2.5. La Anotación @Transient

A veces, puede que deseemos hacer un campo no persistente. Podemos utilizar la anotación @Transient para especificar que el campo no será persistido.

Por ejemplo, podemos calcular la edad de un estudiante a partir de la fecha de nacimiento, así que anotamos el campo age con la anotación @Transient:


@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

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

    @Transient
    private Integer age;

    // otros campos, getters y setters
}

Como resultado, el campo age no se persistirá en la tabla.

2.6. La Anotación @Temporal

En algunos casos, puede que necesitemos guardar valores temporales en nuestra tabla. Para esto, contamos con la anotación @Temporal:


@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

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

    @Transient
    private Integer age;

    @Temporal(TemporalType.DATE)
    private Date birthDate;

    // otros campos, getters y setters
}

Con JPA 3.1, también tenemos soporte para java.time.LocalDate, java.time.LocalTime, java.time.LocalDateTime, java.time.OffsetTime y java.time.OffsetDateTime.

2.7. La Anotación @Enumerated

A veces, es posible que deseemos persistir un tipo enum de Java. Podemos usar la anotación @Enumerated para especificar si la enumeración debe persistirse por nombre o por ordinal (predeterminado):


public enum Gender {
    MALE, 
    FEMALE
}

@Entity
@Table(name="STUDENT")
public class Student {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

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

    @Transient
    private Integer age;

    @Temporal(TemporalType.DATE)
    private Date birthDate;

    @Enumerated(EnumType.STRING)
    private Gender gender;

    // otros campos, getters y setters
}

No tenemos que especificar la anotación @Enumerated si vamos a persistir el Gender por el ordinal del enum. Sin embargo, para persistir el Gender por el nombre del enum, se configura la anotación con EnumType.STRING.

3. Conclusión

En este artículo, aprendimos qué son las entidades JPA y cómo crear y configurar estas entidades utilizando diversas anotaciones. Las entidades son fundamentales para gestionar la persistencia en aplicaciones Java, y comprender cómo utilizarlas eficientemente puede mejorar significativamente la calidad y mantenibilidad de nuestras aplicaciones.

Consejos Prácticos:

  • Siempre define un constructor sin argumentos en tus clases de entidad.
  • Considera usar @Entity con un nombre diferente si tu tabla se llama algo que no puede asociarse directamente con el nombre de la clase.
  • Utiliza @Transient para campos que no necesitas almacenar en la base de datos pero son útiles para el negocio.
  • Aprovecha las nuevas API de fecha y hora en JPA para manejar datos temporales de manera más efectiva.

Siguiendo estas prácticas, estarás en camino de construir eficaces aplicaciones Java que interactúan con bases de datos de manera eficiente y profesional.