Подтвердить что ты не робот

Сравнение объектов даты в API-интерфейсах JPA

Использование 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>>

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

4b9b3361

Ответ 1

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

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

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

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

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

Ответ 2

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

Path<Date> dateCreatedPath = root.get("dateCreated");
predicates.add(builder.lessThanOrEqualTo(dateCreatedPath, dateLimit));

Ответ 3

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