JPA CriteriaBuilder - How to use "IN" comparison operator

HibernateJpaOrmJpa 2.0Criteria Api

Hibernate Problem Overview


Can you please help me how to convert the following codes to using "in" operator of criteria builder? I need to filter by using list/array of usernames using "in".

I also tried to search using JPA CriteriaBuilder - "in" method but cannot find good result. So I would really appreciate also if you can give me reference URLs for this topic. Thanks.

Here is my 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();

The internal Query String is converted to below, so I don't get the records created by the two users, because it is using "AND".

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

Hibernate Solutions


Solution 1 - Hibernate

If I understand well, you want to Join ScheduleRequest with User and apply the in clause to the userName property of the entity User.

I'd need to work a bit on this schema. But you can try with this trick, that is much more readable than the code you posted, and avoids the Join part (because it handles the Join logic outside the Criteria Query).

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

In order to write more type-safe code you could also use Metamodel by replacing this line:

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

with this:

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

If it works, then you may try to add the Join logic into the Criteria Query. But right now I can't test it, so I prefer to see if somebody else wants to try.

Solution 2 - Hibernate

Not a perfect answer though may be code snippets might help.

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

	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJemruView Question on Stackoverflow
Solution 1 - HibernateperissfView Answer on Stackoverflow
Solution 2 - Hibernatebaba.kabiraView Answer on Stackoverflow