JPA/Criteria API - Like & equal problem

90,375

Solution 1

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

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

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

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

Solution 4

Use :

personCriteriaQuery.where(criteriaBuilder.like(
criteriaBuilder.upper(personRoot.get(Person_.description)), 
"%"+filter.getDescription().toUpperCase()+"%")); 
Share:
90,375
John Manak
Author by

John Manak

Updated on July 09, 2022

Comments

  • John Manak
    John Manak almost 2 years

    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?

  • Kalpesh Soni
    Kalpesh Soni about 10 years
    "name" here is the variable name of the parameter here? like :name in jpql?
  • Black Swan
    Black Swan over 6 years
    @axtavt, how i can ignore case
  • Mohammad Faisal
    Mohammad Faisal about 6 years
    will the result of the query be like employee.name like '%<value>%'? Is it possible to achieve like '<value>%'?
  • Paulo 'PaulusHC' Cruz
    Paulo 'PaulusHC' Cruz over 5 years
    Also, you can add a replace in there to make it easier to use, for example: Predicate condition = builder.like(root.<String>get("reference"),reference.replace‌​("*", "%")); This way, you can pass on * as special characters to represent the like behavior.
  • WesternGun
    WesternGun over 2 years
    Of course, in builder.like() method, the second arg can be a String. So you can put sth like Predicate like = builder.like(root.get(Employee_.name), "%joke%").
  • WesternGun
    WesternGun over 2 years
    You mean a char instead of a String? Oh.