JPA CriteriaBuilder-comment utiliser l'opérateur de comparaison "IN"
j'ai aussi essayé d'utiliser la méthode JPA CriteriaBuilder - "in" Mais je n'ai pas trouvé de bon résultat. J'apprécierais donc vraiment aussi si vous pouvez me donner des URLs de référence pour ce sujet. Grâce.
Voici mes codes:
//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 chaîne de requête interne est convertie en ci-dessous, donc je ne reçois pas les enregistrements créés par les deux utilisateurs, parce qu'il utilise "et".
select generatedAlias0 from ScheduleRequest as generatedAlias0 where ( generatedAlias0.createdBy=:param0 ) and ( generatedAlias0.createdBy=:param1 ) order by generatedAlias0.trackingId asc
2 réponses
Si je comprends bien, vous voulez vous Joindre à ScheduleRequest
User
et appliquer les in
clause userName
propriété de l'entité User
.
j'aurais besoin de travailler un peu sur ce schéma. Mais vous pouvez essayer avec ce truc, c'est beaucoup plus lisible que le code que vous avez posté, et évite les Join
part (parce qu'il gère le Join
logique à l'extérieur de la Requête de Critères).
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);
pour écrire plus de code de sécurité, Vous pouvez aussi utiliser Metamodel le remplacement de cette ligne:
Expression<String> exp = scheduleRequest.get("createdBy");
avec ceci:
Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy);
Si cela fonctionne, alors vous pouvez essayer d'ajouter le Join
logique dans le Criteria Query
. Mais pour l'instant je ne peux pas le tester, donc je préfère voir si quelqu'un d'autre veut essayer.
ce n'est pas une réponse parfaite même si des bribes de code pourraient aider.
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);
}