Jakarta Persistence (JPA) en Quarkus: Acceso a Datos con EntityManager
Introducción
Jakarta Persistence (JPA) es la especificación estándar para acceso a datos relacionales en Java. Quarkus implementa JPA completamente a través de Hibernate ORM, proporcionando todas las características de la especificación.
¿Qué es JPA?
JPA proporciona una API estándar para mapear objetos Java a tablas de base de datos relacionales. Permite trabajar con objetos en lugar de SQL directo, aunque también soporta SQL cuando es necesario.
EntityManager: El Corazón de JPA
El EntityManager es la interfaz principal para interactuar con la base de datos:
@Inject
EntityManager entityManager;
@Transactional
public Hero createHero(Hero hero) {
entityManager.persist(hero);
entityManager.flush();
return hero;
}
Operaciones Básicas
CRUD Operations
// Create
entityManager.persist(hero);
// Read
Hero hero = entityManager.find(Hero.class, id);
// Update
hero.setPowerLevel(95);
entityManager.merge(hero);
// Delete
entityManager.remove(hero);
Métodos Avanzados
// Obtener referencia lazy
Hero hero = entityManager.getReference(Hero.class, id);
// Refrescar desde BD
entityManager.refresh(hero);
// Desvincular del contexto
entityManager.detach(hero);
// Verificar si está gestionada
boolean isManaged = entityManager.contains(hero);
// Forzar sincronización
entityManager.flush();
// Limpiar contexto
entityManager.clear();
Named Queries
Las Named Queries se definen en las entidades y se validan en tiempo de compilación:
@Entity
@NamedQueries({
@NamedQuery(
name = "Hero.findAll",
query = "SELECT h FROM Hero h ORDER BY h.name"
),
@NamedQuery(
name = "Hero.findByPowerLevel",
query = "SELECT h FROM Hero h WHERE h.powerLevel >= :minLevel"
)
})
public class Hero {
// ...
}
// Uso
TypedQuery<Hero> query = entityManager.createNamedQuery("Hero.findAll", Hero.class);
List<Hero> heroes = query.getResultList();
JPQL (Java Persistence Query Language)
JPQL permite escribir queries dinámicas usando sintaxis similar a SQL pero orientada a objetos:
String jpql = "SELECT h FROM Hero h WHERE h.powerLevel >= :minLevel";
TypedQuery<Hero> query = entityManager.createQuery(jpql, Hero.class);
query.setParameter("minLevel", 80);
List<Hero> heroes = query.getResultList();
JOIN FETCH (Evitar N+1)
String jpql = "SELECT DISTINCT h FROM Hero h LEFT JOIN FETCH h.missions";
TypedQuery<Hero> query = entityManager.createQuery(jpql, Hero.class);
List<Hero> heroes = query.getResultList();
Criteria API
La Criteria API permite construir queries type-safe programáticamente:
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Hero> query = cb.createQuery(Hero.class);
Root<Hero> hero = query.from(Hero.class);
Predicate powerPredicate = cb.greaterThanOrEqualTo(hero.get("powerLevel"), 80);
query.where(powerPredicate);
query.orderBy(cb.desc(hero.get("powerLevel")));
TypedQuery<Hero> typedQuery = entityManager.createQuery(query);
List<Hero> heroes = typedQuery.getResultList();
Relaciones entre Entidades
OneToMany
@Entity
public class Hero {
@OneToMany(mappedBy = "hero", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Mission> missions;
}
ManyToOne
@Entity
public class Mission {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "hero_id", nullable = false)
private Hero hero;
}
Lifecycle Callbacks
Los callbacks permiten ejecutar código en diferentes momentos del ciclo de vida:
@Entity
public class Hero {
@PrePersist
protected void onCreate() {
createdAt = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updatedAt = LocalDateTime.now();
}
@PostLoad
protected void onLoad() {
// Inicializar colecciones lazy
}
}
Optimistic Locking
El @Version permite implementar optimistic locking:
@Entity
public class Hero {
@Version
private Long version;
}
Ejemplo Completo
Nuestro demo muestra:
EntityManager con todas sus operaciones
Named Queries
JPQL queries dinámicas
Criteria API
Relaciones OneToMany/ManyToOne
Lifecycle callbacks
Optimistic locking
Ventajas en Quarkus
Implementación Completa: Todas las características de JPA
Integración CDI: EntityManager inyectable con @Inject
Performance: Hibernate optimizado para Quarkus
Startup Rápido: Procesamiento en tiempo de compilación
Conclusión
JPA en Quarkus proporciona acceso completo a bases de datos relacionales con todas las características de la especificación. La integración con CDI y Transactions hace que sea muy fácil de usar.




