JPA/Criteria API - Like & equal problem

JavaJpaJpa 2.0Criteria Api

Java Problem Overview


I'm trying to use Criteria API in my new project:

public List<Employee> findEmps(String name) {
	CriteriaBuilder cb = em.getCriteriaBuilder();
	CriteriaQuery<Employee> c = cb.createQuery(Employee.class);
	Root<Employee> emp = c.from(Employee.class);
	c.select(emp);
	c.distinct(emp);
	List<Predicate> criteria = new ArrayList<Predicate>();
	
	if (name != null) {
		ParameterExpression<String> p = cb.parameter(String.class, "name");
		criteria.add(cb.equal(emp.get("name"), p));
	}

	/* ... */
	
	if (criteria.size() == 0) {
		throw new RuntimeException("no criteria");
	} else if (criteria.size() == 1) {
		c.where(criteria.get(0));
	} else {
		c.where(cb.and(criteria.toArray(new Predicate[0])));
	}
	
	TypedQuery<Employee> q = em.createQuery(c);
	
	if (name != null) {
		q.setParameter("name", name);
	}
	
	/* ... */
	
	return q.getResultList();
}

Now when I change this line:

			criteria.add(cb.equal(emp.get("name"), p));

to:

			criteria.add(cb.like(emp.get("name"), p));

I get an error saying:

> The method like(Expression, Expression) in the type CriteriaBuilder is not > applicable for the arguments (Path, ParameterExpression)

What's the problem?

Java Solutions


Solution 1 - Java

Perhaps you need

criteria.add(cb.like(emp.<String>get("name"), p));

because first argument of like() is Expression<String>, not Expression<?> as in equal().

Another approach is to enable generation of the static metamodel (see docs of your JPA implementation) and use typesafe Criteria API:

criteria.add(cb.like(emp.get(Employee_.name), p));

(Note that you can't get static metamodel from em.getMetamodel(), you need to generate it by external tools).

Solution 2 - Java

Better: predicate (not ParameterExpression), like this :

List<Predicate> predicates = new ArrayList<Predicate>();
if(reference!=null){
	Predicate condition = builder.like(root.<String>get("reference"),"%"+reference+"%");
	predicates.add(condition);
}

Solution 3 - Java

It will work with a small addition of .as(String.class):

criteria.add(cb.like(emp.get("name").as(String.class), p));

Solution 4 - Java

Use :

personCriteriaQuery.where(criteriaBuilder.like(
criteriaBuilder.upper(personRoot.get(Person_.description)), 
"%"+filter.getDescription().toUpperCase()+"%")); 

Solution 5 - Java

I tried all the proposals and although it did not give an error, it did not recover anything if I did not put all the expected text, in the end what was proposed by user3077341 worked for me but with the variant that I use '%' instead of "%", the like worked perfect.

List<Predicate> predicates = new ArrayList<Predicate>();
if(reference!=null){
    Predicate condition = builder.like(root.<String>get("reference"),'%'+reference+'%');
    predicates.add(condition);
}

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
QuestionJohn ManakView Question on Stackoverflow
Solution 1 - JavaaxtavtView Answer on Stackoverflow
Solution 2 - Javauser3077341View Answer on Stackoverflow
Solution 3 - JavaChristophView Answer on Stackoverflow
Solution 4 - JavaAbdessamad HALLALView Answer on Stackoverflow
Solution 5 - JavarramirezechView Answer on Stackoverflow