I have a simplified Entity
class like this:
@Entity
public class Student {
String name;
Date birthday;
Integer term;
}
A third party dependency (DataTables) is sending a search request in form of a Map<String,String>
where the key
is the name of the entity's attribut and the value
the search String
. A map can look like this:
key | value
------------------
name | Alice
birthday | 2000
term | 3
I currently use this implementation, which works fine for String
attributes like name
:
public List<Student> getStudents(Map<String,String> filters) throws Exception {
//get builder
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery cq = cb.createQuery();
Root<Student> student = cq.from(Student.class);
//validate if attribut exists
try {
for(String key : filters.keySet()) {
student.get(key); //check if path exists
}
} catch (IllegalStateException | IllegalArgumentException ex ) {
throw new Exception("Invalid filter parameters!");
}
// select
cq.select(student);
//where
Predicate wherePredicate = cb.and(); // init with true;
for (Entry<String,String> filter : filters.entrySet()) {
wherePredicate = cb.and(wherePredicate,
cb.like(student.get(filter.getKey()), "%"+filter.getValue()+"%"));
}
cq.where(wherePredicate);
return entityManager.createQuery(cq).getResultList();
}
Of course, the like
criteria does not work for Integer
or Date
. How can I extent my code to define criterias based on the attributes data type?
I tried this, what unfortuantly is not possible in Java:
switch (student.get(filter.getKey()).getClass()) {
case Path<String>.class:
return cb.like(student.get(filter.getKey()), "%"+filter.getValue()+"%");
case Path<Integer>.class:
return cb.equal(student.get(filter.getKey()), filter.getValue())
}