1. Información general
A menudo nos encontramos con problemas en los que necesitamos consultar entidades en función de si un atributo de valor único es miembro de una colección determinada.
En este tutorial, aprenderemos cómo resolver este problema con la ayuda de Criteria API.
2. Entidades de muestra
Antes de comenzar, echemos un vistazo a las entidades que usaremos en nuestro artículo.
Tenemos una clase DeptEmployee que tiene una relación de varios a uno con una clase de Departamento :
@Entity public class DeptEmployee { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String title; @ManyToOne private Department department; }
Además, la entidad del Departamento que se asigna a varios DeptEmployees :
@Entity public class Department { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private long id; private String name; @OneToMany(mappedBy="department") private List employees; }
3. El CriteriaBuilder.In
En primer lugar, usemos la interfaz CriteriaBuilder . El método in () acepta una expresión y devuelve un nuevo predicado del tipo CriteriaBuilder.In . Puede usarse para probar si la expresión dada está contenida en la lista de valores:
CriteriaQuery criteriaQuery = criteriaBuilder.createQuery(DeptEmployee.class); Root root = criteriaQuery.from(DeptEmployee.class); In inClause = criteriaBuilder.in(root.get("title")); for (String title : titles) { inClause.value(title); } criteriaQuery.select(root).where(inClause);
4. La expresión. En
Alternativamente, podemos usar un conjunto de métodos in () sobrecargados desde la interfaz Expression :
criteriaQuery.select(root) .where(root.get("title") .in(titles));
En contraste con CriteriaBuilder. in () , Expression.in () acepta una colección de valores. Como podemos ver, también simplifica un poco nuestro código.
5. Expresiones IN usando subconsultas
Hasta ahora, hemos utilizado colecciones con valores predefinidos. Ahora, echemos un vistazo a un ejemplo cuando una colección se deriva de la salida de una subconsulta.
Por ejemplo, podemos buscar todos los empleados del departamento que pertenecen a un departamento, con la palabra clave especificada en su nombre:
Subquery subquery = criteriaQuery.subquery(Department.class); Root dept = subquery.from(Department.class); subquery.select(dept) .distinct(true) .where(criteriaBuilder.like(dept.get("name"), "%" + searchKey + "%")); criteriaQuery.select(emp) .where(criteriaBuilder.in(emp.get("department")).value(subquery));
Aquí, creamos una subconsulta que luego se pasó al valor () como una expresión para buscar la entidad Departamento .
6. Conclusión
En este artículo rápido, hemos aprendido diferentes formas de lograr la operación IN utilizando la API Criteria. También hemos explorado cómo utilizar la API de criterios con subconsultas.
Finalmente, la implementación completa de este tutorial está disponible en GitHub.