2012-02-17 24 views
34

Potete aiutarmi come convertire i seguenti codici nell'utilizzo dell'operatore "in" del generatore di criteri? Ho bisogno di filtrare usando lista/array di nomi utente usando "in".JPA CriteriaBuilder - Come utilizzare l'operatore di confronto "IN"

Ho anche provato a cercare utilizzando JPA CriteriaBuilder - metodo "in" ma non riesco a trovare un buon risultato. Quindi mi piacerebbe davvero anche se mi puoi dare URL di riferimento per questo argomento. Grazie.

Ecco i miei codici:

//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(); 

The String interno query viene convertita al di sotto, quindi non si ottiene il record creati dai due utenti, perché sta usando "AND".

select generatedAlias0 from ScheduleRequest as generatedAlias0 where (generatedAlias0.createdBy=:param0) and (generatedAlias0.createdBy=:param1) order by generatedAlias0.trackingId asc 

risposta

69

Se ho capito bene, si desidera partecipare ScheduleRequest con User e applicare la clausola in alla userName proprietà dell'entità User.

Avrei bisogno di lavorare un po 'su questo schema. Ma puoi provare con questo trucco, che è molto più leggibile rispetto al codice che hai postato, ed evita la parte Join (perché gestisce la logica al di fuori della Query criteri).

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); 

Per scrivere più codice type-safe si potrebbe anche usare Metamodel sostituendo questa linea:

Expression<String> exp = scheduleRequest.get("createdBy"); 

con questo:

Expression<String> exp = scheduleRequest.get(ScheduleRequest_.createdBy); 

Se funziona, allora si può prova ad aggiungere la logica Join allo Criteria Query. Ma al momento non posso testarlo, quindi preferisco vedere se qualcun altro vuole provare.

+0

Ciao perissf, grazie per la tua risposta. Posso chiederlo per favore, che cos'è "ScheduleRequest_"? Come lo creo? – Jemru

+2

È una classe Metamodel generata automaticamente dal tuo provider JPA. Se stai usando Hibernate, controlla questo link http://docs.jboss.org/hibernate/jpamodelgen/1.0/reference/en-US/html_single/ – perissf

+0

Leggendo il mio pseudo-codice, vedo una possibile discrepanza di tipo. Ti unisci a userNames (String) o userIds (Integer/Long)? Pls fammi sapere in modo che possa aggiornare la mia risposta – perissf

13

Non è una risposta perfetta anche se può essere frammenti di codice potrebbe aiutare.

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); 

    } 
+1

Grazie mille @gbagga, questa cosa mi ha aiutato molto! il metodo precedente (exp.in (myList)) non funzionerà quando si utilizza "CriteriaBuilder". Il tuo metodo è quello che dovrebbe essere usato per la clausola "IN" quando si usa criteriaBuilder. Complimenti! – roneo

Problemi correlati