Идея состоит в том, чтобы предоставить ограничения для предложения where в «операторе SQL».
SELECT * FROM table_name WHERE key=value
Многим людям нравится писать JPQL-запросы, похожие на SQL, потому что их легче понять при чтении. Тем не менее, есть некоторые преимущества использования этого Criteria API (динамический, меньше подвержен ошибкам, меньше внимания для безопасности, легче реорганизовать).
Первый шаг - получить CriteriaBuilder
, а затем создать CriteriaQuery
с этим. После этого вы можете определить, из какого класса вы хотите построить Root
, и использовать его для получения столбцов. Также могут следовать объединения.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<YourClass> cq = cb.createQuery(YourClass.class);
Root<YourClass> root = cq.from(YourClass.class);
В качестве следующего шага вы хотите определить предложение where с его ограничениями (предикатами). Как и в обычном операторе SQL, там может быть только один оператор. Если у вас есть несколько ограничений, их необходимо объединить с criteriaBuilder.and()
.
Существует несколько способов применения всего процесса. У меня есть один способ, как я это делаю (и некоторые другие тоже могут это делать). Обычно я создаю List
со всеми ограничениями, которые я хочу использовать, и создаю из него массив, который затем объединяется с cb.and()
.
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get("key1"), "value1"));
predicates.add(cb.gt(root.get("key2"), 100));
cq.select(root).where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
Ниже приведен целый пример такого DAO. method.
public List<Foo>(String state, int size, String column, String value) {
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Foo> cq = cb.createQuery(Foo.class);
Root<Foo> root = cq.from(Foo.class);
List<Predicate> predicates = new ArrayList<>();
predicates.add(cb.equal(root.get(Foo_.bla), state));
predicates.add(cb.gt(root.get(Foo_.blub), size));
predicates.add(cb.equal(root.get(column), value));
cq.select(root).where(cb.and(predicates.toArray(new Predicate[predicates.size()])));
return entityManager.createQuery(cq).getResultList();
}
Для получения имен столбцов (или сингулярных атрибутов) я использовал hibernate-jpamodelgen
. Посмотрите на этот плагин, который автоматически генерирует классы (Foo_
), что делает его более безопасным при использовании имен столбцов.
Обновление: если вы не знаете имен столбцов для ограничений в предложении whereзаранее его просто отрегулировать (см. третье ограничение выше).