JPA EntityManager createQuery () с IN не работает - PullRequest
6 голосов
/ 25 июня 2010

Это не удалось:

List<String> names = new ArrayList<String>();
names.add("sold");
Query query = em.createQuery("FROM PropField propField WHERE propField.name IN (?)");
query.setParameter(1, names);
List<PropField> fields = query.getResultList();

И вот так:

List<String> names = new ArrayList<String>();
names.add("sold");
Query query = em.createQuery("FROM PropField propField WHERE propField.name IN (?)");
query.setParameter(1, names.toArray());
List<PropField> fields = query.getResultList();

Это тоже:

List<String> names = new ArrayList<String>();
names.add("sold");
Query query = em.createQuery("FROM PropField propField WHERE propField.name IN ?");
query.setParameter(1, names.toArray());
List<PropField> fields = query.getResultList();

И любая другая перестановка вышеперечисленного. Проверил документы, и он говорит, что первый вариант должен работать. Вот исключение для верхнего.

java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String
at org.hibernate.type.StringType.toString(StringType.java:67)

HQL Hibernate использует setParameterList, но пытается придерживаться прямого JPA здесь.

Ответы [ 3 ]

20 голосов
/ 25 июня 2010

Из спецификации JPA 1.0:

4.6.4.1 Позиционные параметры

Следующие правила применяются к позиционным параметрам.

  • Входные параметры обозначаются префиксом вопросительного знака (?), За которым следует целое число. Например: ?1.
  • Входные параметры нумеруются, начиная с 1.
    Обратите внимание, что один и тот же параметр может использоваться более одного раза в строке запроса и что порядок использования параметров в строке запроса не обязательно должен соответствовать порядку позиционных параметров.

4.6.4.2 Именованные параметры

Именованный параметр - это идентификатор, перед которым ставится символ «:». Он следует правилам для идентификаторов, определенных в разделе 4.4.1. Именованные параметры чувствительны к регистру.

* * Пример тысяча двадцать-один: * * 1 022
SELECT c
FROM Customer c
WHERE c.status = :stat

Раздел 3.6.1 описывает API для привязки именованных параметров запроса

Так что либо используйте (с именованным параметром):

List<String> names = Arrays.asList("sold");
Query query = em.createQuery("FROM PropField propField WHERE propField.name IN (:names)");
query.setParameter("names", names)
List<PropField> fields = query.getResultList();

Или (с позиционным параметром):

List<String> names = Arrays.asList("sold");
Query query = em.createQuery("FROM PropField propField WHERE propField.name IN (?1)");
query.setParameter(1, names)
List<PropField> fields = query.getResultList();

Оба протестированы с Hibernate EM 3.4.0.GA.

Обратите внимание, что принудительное использование скобок для окружения параметра предложения IN является ошибкой (по крайней мере, в JPA 2.0), как указано в в этом предыдущем ответе .

1 голос
/ 25 июня 2010

Я столкнулся с подобной проблемой в Hibernate, используя именованный запрос JPA с предложением IN.Я получил это работает с синтаксисом: "propField.name IN (? 1)"

Также см .: http://opensource.atlassian.com/projects/hibernate/browse/HHH-4922

и http://opensource.atlassian.com/projects/hibernate/browse/HHH-5126

0 голосов
/ 25 июня 2010

У меня нет доступа к среде Hibernate, чтобы попробовать это, но вы пробовали

Query query = em.createQuery("FROM PropField propField WHERE propField.name IN elements(?)");
query.setParameter(1, names);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...