hibernate - manager - java criteriabuilder example
JPA CriteriaBuilder-Cómo utilizar el operador de comparación "IN" (2)
¿Puede ayudarme por favor cómo convertir los siguientes códigos para usar el operador "in" del creador de criterios? Necesito filtrar usando list / array de nombres de usuario usando "in".
También traté de buscar utilizando JPA CriteriaBuilder - método "in" pero no puedo encontrar un buen resultado. Por lo tanto, realmente agradecería que me dieran URL de referencia para este tema. Gracias.
Aquí están mis códigos:
//usersList is a list of User that I need to put inside IN operator
CriteriaBuilder builder = getJpaTemplate().getEntityManagerFactory().getCriteriaBuilder();
CriteriaQuery<ScheduleRequest> criteria = builder.createQuery(ScheduleRequest.class);
Root<ScheduleRequest> scheduleRequest = criteria.from(ScheduleRequest.class);
criteria = criteria.select(scheduleRequest);
List<Predicate> params = new ArrayList<Predicate>();
List<ParameterExpression<String>> usersIdsParamList = new ArrayList<ParameterExpression<String>>();
for (int i = 0; i < usersList.size(); i++) {
ParameterExpression<String> usersIdsParam = builder.parameter(String.class);
params.add(builder.equal(scheduleRequest.get("createdBy"), usersIdsParam) );
usersIdsParamList.add(usersIdsParam);
}
criteria = criteria.where(params.toArray(new Predicate[0]));
TypedQuery<ScheduleRequest> query = getJpaTemplate().getEntityManagerFactory().createEntityManager().createQuery(criteria);
for (int i = 0; i < usersList.size(); i++) {
query.setParameter(usersIdsParamList.get(i), usersList.get(i).getUsername());
}
List<ScheduleRequest> scheduleRequestList = query.getResultList();
La cadena de consulta interna se convierte a continuación, por lo que no obtengo los registros creados por los dos usuarios, porque está utilizando "Y".
select generatedAlias0 from ScheduleRequest as generatedAlias0 where ( generatedAlias0.createdBy=:param0 ) and ( generatedAlias0.createdBy=:param1 ) order by generatedAlias0.trackingId asc
Aunque no es una respuesta perfecta, los fragmentos de código pueden ser útiles.
public <T> List<T> findListWhereInCondition(Class<T> clazz,
String conditionColumnName, Serializable... conditionColumnValues) {
QueryBuilder<T> queryBuilder = new QueryBuilder<T>(clazz);
addWhereInClause(queryBuilder, conditionColumnName,
conditionColumnValues);
queryBuilder.select();
return queryBuilder.getResultList();
}
private <T> void addWhereInClause(QueryBuilder<T> queryBuilder,
String conditionColumnName, Serializable... conditionColumnValues) {
Path<Object> path = queryBuilder.root.get(conditionColumnName);
In<Object> in = queryBuilder.criteriaBuilder.in(path);
for (Serializable conditionColumnValue : conditionColumnValues) {
in.value(conditionColumnValue);
}
queryBuilder.criteriaQuery.where(in);
}
Si lo entiendo bien, desea unirse a ScheduleRequest
con el User
y aplicar la cláusula in
a la propiedad userName
del User
de la entidad.
Tendría que trabajar un poco en este esquema. Pero puedes probar con este truco, que es mucho más legible que el código que publicaste, y evita la parte de Join
(porque maneja la lógica de Join
fuera de la consulta de criterios).
List<String> myList = new ArrayList<String> ();
for (User u : usersList) {
myList.add(u.getUsername());
}
Expression<String> exp = scheduleRequest.get("createdBy");
Predicate predicate = exp.in(myList);
criteria.where(predicate);
Para escribir más código seguro, también podría usar Metamodel reemplazando esta línea:
Expression<String> exp = scheduleRequest.get("createdBy");
con este:
Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy);
Si funciona, puede intentar agregar la lógica de Join
a la Criteria Query
. Pero ahora mismo no puedo probarlo, así que prefiero ver si alguien más quiere probarlo.