У меня есть упрощенный класс Entity
, подобный этому:
@Entity
public class Student {
String name;
Date birthday;
Integer term;
}
Сторонняя зависимость (DataTables) отправляет запрос на поиск в виде Map<String,String>
, где key
- это имяатрибута сущности и value
поиска String
.Карта может выглядеть следующим образом:
key | value
------------------
name | Alice
birthday | 2000
term | 3
В настоящее время я использую эту реализацию, которая отлично работает для String
атрибутов, таких как 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();
}
Конечно, критерии like
не работают для Integer
или Date
. Как я могу расширить свой код для определения критериев, основанных на типе данных атрибутов?
Я пробовал это, что, к сожалению, невозможно в 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())
}