BookinglyTech News
Software

EasyJPA envuelve la Criteria API de JPA en cadenas de lambdas tipadas

El starter de Spring Boot sustituye el ceremonial de CriteriaBuilder, Root y Predicate[] por consultas encadenadas con referencias a métodos. Se instala en dos pasos y la versión actual es un snapshot.

3 min de lecturaDev.to0 vistas

EasyJPA es un starter de Spring Boot que monta una API fluida basada en lambdas sobre la Criteria API de JPA. La promesa es conservar la seguridad de tipos y la construcción dinámica de consultas que da Criteria, pero quitando de en medio el CriteriaBuilder, el Root y el array de Predicate[] que vuelven ilegible el código. Joins, subconsultas, agrupación, paginación, updates, deletes y SQL nativo caben en una cadena que se lee de arriba abajo. El proyecto está publicado en GitHub.

De treinta líneas a tres

El ejemplo que usa el autor es una consulta por usuario y contraseña. Con Criteria puro hay que obtener el CriteriaBuilder, crear la CriteriaQuery, declarar el Root, acumular predicados en una lista, convertirla a array y lanzar la query. Con EasyJPA queda así:

User user = userDao.query()
    .filter(new FilterList().eq(User::getUsername, "Jack").eq(User::getPassword, "123456"))
    .selectThis().one();

Misma consulta, mismo SQL generado y misma comprobación de tipos. La diferencia de fondo es que cada condición acepta una referencia a método, así que renombrar un campo de la entidad rompe la compilación en lugar de aparecer como excepción en tiempo de ejecución.

Para filtros sueltos está Restrictions, que construye una condición única, y FilterList, que encadena varias. La negación no es una clase aparte: se resuelve con .not() sobre la condición, y las alternativas con .or(). Las condiciones anidan igual que se escribirían en una pizarra, de modo que un filtro del tipo "vip o (username in (...) y email no nulo)" se traduce línea a línea.

Los joins se declaran por lambda y cada uno lleva un alias corto que se reutiliza después. La gracia es que la lambda arrastra su propia entidad, así que un segundo join puede ramificar desde una tabla intermedia en lugar de continuar desde la última. Existen también leftJoin, rightJoin y crossJoin, y la condición del on es simplemente el tercer argumento. Para agrupaciones hay groupBy con lista de campos y select con columnas agregadas —count, sum— a las que se les pone alias para mapear el resultado directamente a un VO.

Instalación y encaje

El montaje son dos pasos. Primero la dependencia com.github.paganini2008:easyjpa-spring-boot-starter, en versión 2.0.0-SNAPSHOT para Spring Boot 4 y 1.0.0-SNAPSHOT si se sigue en Spring Boot 3. Al ser un snapshot hay que declarar explícitamente el repositorio de snapshots del Central Portal. Segundo, apuntar Spring Data a la implementación de repositorio del proyecto con @EnableJpaRepositories(repositoryFactoryBeanClass = HibernateEntityDaoFactoryBean.class) junto a @EntityScan.

A partir de ahí los DAO extienden EntityDao en vez de JpaRepository. El matiz importa: EntityDao es un JpaRepository, así que save, findById, deleteAll y el resto siguen disponibles. EasyJPA solo añade los constructores de consulta encima.

El atractivo es evidente para quien pelea cada semana con Specifications o con cadenas JPQL montadas a mano cuando el filtro es dinámico. La advertencia también: las versiones publicadas son snapshots, atadas a Spring Boot 4 la actual, y un snapshot puede cambiar sin aviso ni garantía de estabilidad. Para producción conviene esperar a una release cerrada, o quedarse en la rama de Spring Boot 3 si el salto de framework no está sobre la mesa. Ejemplos y código de prueba contra un esquema de comercio electrónico, con User, Order, OrderProduct, Product y Stock, están en el repositorio.