Сравнение сущностей даты в API критериев JPA - PullRequest
41 голосов
/ 26 февраля 2012

Использование JPA 2 с реализацией EclipseLink.

Я пытаюсь создать динамический запрос, который должен принести мне несколько записей, сохраненных после указанной даты.

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<Event> criteria = builder.createQuery(Event.class);
Root<Event> root = criteria.from(Event.class);
criteria.select(root);
criteria.distinct(true);
List<Predicate> predicates = new ArrayList<Predicate>();
//...
if (dateLimit != null){
    ParameterExpression<Date> param = builder.parameter(Date.class, "dateLimit");
    predicates.add(builder.lessThanOrEqualTo(root.get("dateCreated"), param));
}

lessThanOrEqualTo() и le() - это единственные два метода в API, которые могут помочь мне в этом случае. Это предупреждение выдается затмением, хотя:

Bound mismatch: The generic method lessThanOrEqualTo(Expression<? extends Y>, Expression<? extends Y>)
of type CriteriaBuilder is not applicable for the arguments (Path<Object>, ParameterExpression<Date>).
The inferred type Object is not a valid substitute for the bounded parameter
<Y extends Comparable<? super Y>>

Я могу представить, что я не принимаю правильного подхода к этой проблеме, но я нигде не могу найти несколько советов или указателей для возможного решения.

Ответы [ 3 ]

69 голосов
/ 26 февраля 2012

Проблема состоит в том, что с помощью API на основе строк он не может определить тип для значения результата операции get. Это объясняется, например, в Javadoc для пути .

Если вы используете

predicates.add(builder.lessThanOrEqualTo(root.<Date>get("dateCreated"), param));

Вместо этого он будет работать нормально, потому что он может определить тип возвращаемого значения из аргумента типа и выяснить, что он сопоставим. Обратите внимание, что использование параметризованного вызова метода root.<Date>get(...) (см., Например, Когда полезен вызов параметризованного метода? ).

Другое (на мой взгляд, лучшее) решение - использовать API на основе метамодели вместо строкового. Простой пример канонической метамодели приведен, например, здесь . Если у вас есть больше времени для инвестирования, это хорошая статья о статической метамодели: Динамические, безопасные для типов запросы в JPA 2.0

15 голосов
/ 26 февраля 2012

Вам нужно использовать сгенерированную метамодель для доступа к атрибутам - это действительно безопасный способ.Если вы используете Strings для ссылки на свои атрибуты, типы могут быть выведены только из явного универсального типа, используемого при вызове метода, или путем преобразования типа, или из автоматического вывода типа, сделанного компилятором:

Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));
2 голосов
/ 20 января 2017

Я получил похожую ошибку, но с синтаксисом predicates.add(cb.greaterThan(article.get(Article_.created), since)); и нашел эту страницу. Причиной для меня, оказалось, было то, что я обновил свой проект с Java 1.7 до 1.8, и в процессе настроил Maven для компиляции также для Java 1.8. Мне просто пришлось изменить компиляцию Maven обратно на 1,7, сохранив остальную часть проекта на 1,8, чтобы исправить ошибку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...