MascotaEntity
id es generado; nombre es obligatorio; microchip es único. @ManyToOne con @JoinColumn(name="refugio_id") crea la llave foránea. La lista de adopciones usa mappedBy="mascota" y no crea columna en MASCOTA_ENTITY.
Una clase con @Entity se mapea a una tabla. @Id identifica su llave primaria y @GeneratedValue permite que la base de datos genere el identificador.
@Data@Entitypublic class EmployeeEntity { @Id private Long id; private String name; private Double salary;}@Data?@Data es una anotación de Lombok, no de JPA. Durante la compilación genera automáticamente métodos que normalmente habría que escribir a mano:
toString();equals() y hashCode();@Data reduce código repetitivo en la clase Java, pero no crea tablas ni decide cómo se persiste la entidad. El mapeo con la base de datos comienza con @Entity, @Id y las demás anotaciones de JPA.
En este caso, los atributos se representan como columnas de EMPLOYEE_ENTITY. Un repository declara el tipo de entidad y el tipo de su identificador:
public interface EmployeeRepository extends JpaRepository<EmployeeEntity, Long> {}Spring provee operaciones como save, findById, findAll y delete.
En una relación uno a muchos, el lado con @ManyToOne es propietario y contiene la llave foránea. El lado inverso usa mappedBy y no crea una columna adicional.
// DepartmentEntity: lado inverso@OneToMany(mappedBy = "department", fetch = FetchType.LAZY)private List<EmployeeEntity> employees;
// EmployeeEntity: lado propietario@ManyToOneprivate DepartmentEntity department;FetchType.LAZY?El atributo fetch determina cuándo se carga una relación desde la base de datos.
FetchType.LAZY: al consultar el departamento, JPA no necesita cargar inmediatamente todos sus empleados. La colección se solicita cuando el código intenta acceder a ella.FetchType.EAGER: la relación debe quedar disponible junto con la entidad principal, aunque el código todavía no la haya utilizado.DepartmentEntity department = departmentRepository.findById(id).get();
// Con LAZY, acceder a la colección puede provocar su consulta en este momento.List<EmployeeEntity> employees = department.getEmployees();LAZY evita cargar grafos completos de entidades cuando una operación solo necesita los datos del departamento. El acceso a la colección debe realizarse mientras el contexto de persistencia correspondiente siga disponible.
La tabla EMPLOYEE_ENTITY contiene DEPARTMENT_ID. El mismo patrón se aplica a CompanyEntity y DepartmentEntity: una compañía tiene muchos departamentos y cada departamento pertenece a una compañía.
MascotaEntity
id es generado; nombre es obligatorio; microchip es único. @ManyToOne con @JoinColumn(name="refugio_id") crea la llave foránea. La lista de adopciones usa mappedBy="mascota" y no crea columna en MASCOTA_ENTITY.
RefugioEntity
Tiene nombre obligatorio, dirección, teléfono y capacidad. Sus listas de mascotas y adopciones son relaciones @OneToMany inversas; las llaves foráneas viven en las otras tablas.
AdopcionEntity
Incluye fecha obligatoria, nombre y teléfono del adoptante. Dos relaciones @ManyToOne crean mascota_id y refugio_id en ADOPCION_ENTITY.
Los tipos Java se traducen a tipos SQL: String a VARCHAR, Integer a INTEGER, Long a BIGINT y LocalDate a DATE. JPA requiere un constructor vacío para las entidades.
Selecciona una entidad y observa cómo sus atributos y relaciones aparecen en las tablas.
@EntityLlaves y columnasMuchas mascotas pertenecen a un refugio
REFUGIO_IDUna mascota tiene un historial de adopciones
MASCOTA_ID vive en ADOPCION_ENTITYMASCOTA_ENTITY| ID | NOMBRE | EDAD | MICROCHIP | REFUGIO_ID |
|---|---|---|---|---|
| 1 | Luna | 3 | 2023-0001 | 1 |
| 2 | Max | 5 | 2023-0002 | 1 |
| 3 | Bella | 2 | 2023-0003 | 2 |
@ElementCollection@ElementCollection persiste colecciones de tipos básicos o embebibles sin identidad independiente. Crea una tabla separada con una relación uno a muchos hacia la entidad propietaria.
@ElementCollection |
@OneToMany |
|---|---|
| Valores sin identificador propio | Entidades con identificador |
| Solo tienen sentido dentro del padre | Pueden existir y consultarse independientemente |
Es apropiado para contactos, etiquetas, categorías, historiales numéricos y otros valores múltiples simples. No conviene para objetos con identidad, metadatos propios, grandes volúmenes o consultas independientes frecuentes.
@ElementCollection@CollectionTable( name = "producto_tags", joinColumns = @JoinColumn(name = "producto_id"))@Column(name = "tag")private Set<String> tags;JPA crea PRODUCTO y PRODUCTO_TAGS; esta última contiene producto_id y tag.
@ElementCollection@CollectionTable(name = "calificaciones")@Column(name = "nota")private List<Double> notas;También se pueden declarar varias colecciones en una entidad, por ejemplo correos, teléfonos y habilidades de un usuario; cada colección tiene su tabla.
Las anotaciones relacionadas son:
@ElementCollection: declara la colección.@CollectionTable: personaliza tabla y llave foránea.@Column: personaliza la columna del valor.@OrderColumn: conserva el orden de una lista.@Enumerated: define cómo persistir enums.Complete la relación compañía–departamentos:
// CompanyEntity (mappedBy = "company") private List<DepartmentEntity> departments; // DepartmentEntity private CompanyEntity company;
Complete una colección de etiquetas:
@CollectionTable(name = "producto_tags", joinColumns = @JoinColumn(name = "producto_id")) (name = "tag") private Set<String> tags;