Список передачи JPA в предложение IN в именованном собственном запросе - PullRequest
27 голосов
/ 08 июня 2011

Я знаю, что могу передать список именованному запросу в JPA, но как насчет NamedNativeQuery? Я пробовал много способов, но все еще не могу просто передать список в NamedNativeQuery. Кто-нибудь знает, как передать список в предложении в NamedNativeQuery? Большое спасибо!

NamedNativeQuery как показано ниже:

@NamedNativeQuery(
   name="User.findByUserIdList", 
   query="select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?userIdList)"
)

и это называется так:

List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();

Однако результат не такой, как я ожидал.

System.out.println(userList.size());  //output 1

Object[] user = userList.get(0);
System.out.println(user.length);   //expected 5 but result is 3
System.out.println(user[0]);       //output MDAVERSION which is not a user_id
System.out.println(user[1]);       //output 5
System.out.println(user[2]);       //output 7

Ответы [ 7 ]

16 голосов
/ 08 июня 2011

Список не является допустимым параметром для собственного запроса SQL, поскольку его нельзя связать в JDBC.У вас должен быть параметр для каждого аргумента в списке.

где u.user_id в (? Id1,? Id2)

Это поддерживается через JPQL, но не через SQL, так что вы могли быиспользуйте JPQL вместо собственного запроса.

Некоторые поставщики JPA могут поддерживать это, поэтому вы можете захотеть сообщить об ошибке своему поставщику.

8 голосов
/ 11 июня 2018

Приведенный выше ответ неверен и вывел меня из колеи на многие дни !!

JPA и Hibernate принимают коллекции в собственном запросе с использованием Query.

Вам просто нужно сделать

String nativeQuery = "Select * from A where name in :names"; //use (:names) for older versions of hibernate
Query q = em.createNativeQuery(nativeQuery);
q.setParameter("names", l);

Также см. Ответы здесь, которые предлагают то же самое (я выбрал приведенный выше пример из одного из них)

  1. Ссылка 1
  2. Ссылка 2, в которой упоминается, в каких случаях работает парантез, и который дает список в качестве параметра
3 голосов
/ 09 марта 2018

В зависимости от вашей базы данных / провайдера / драйвера / и т. Д. Вы можете фактически передать список в качестве связанного параметра в собственный запрос JPA.

Например, с Postgres и EclipseLink, следующие работы (возвращающие true), демонстрирующие многомерные массивы и как получить массив двойной точности. (Выполните SELECT pg_type.* FROM pg_catalog.pg_type для других типов; возможно, с _, но удалите его перед использованием.)

Array test = entityManager.unwrap(Connection.class).createArrayOf("float8", new Double[][] { { 1.0, 2.5 }, { 4.1, 5.0 } });
Object result = entityManager.createNativeQuery("SELECT ARRAY[[CAST(1.0 as double precision), 2.5],[4.1, 5.0]] = ?").setParameter(1, test).getSingleResult();

Есть приведение, поэтому буквенный массив состоит из двойных, а не числовых.

Суть вопроса - я не знаю, как и если вы можете делать именованные запросы; Я думаю, это зависит, может быть. Но я думаю, что следующий будет работать для Array.

Array list = entityManager.unwrap(Connection.class).createArrayOf("int8", arrayOfUserIds);
List<Object[]> userList = entityManager.createNativeQuery("select u.* from user u "+
     "where u.user_id = ANY(?)")
     .setParameter(1, list)
     .getResultList();

У меня нет той же схемы, что и у OP, поэтому я не проверил это точно, но я думаю, что она должна работать - опять же, по крайней мере, на Postgres & EclipseLink.

Также ключ был найден в: http://tonaconsulting.com/postgres-and-multi-dimensions-arrays-in-jdbc/

1 голос
/ 12 июня 2018

Используя hibernate, JPA 2.1 и данные deltaspike, я мог бы передать список в качестве параметра в запросе, который содержит предложение IN. мой запрос ниже.

@Query(value = "SELECT DISTINCT r.* FROM EVENT AS r JOIN EVENT AS t on r.COR_UUID = t.COR_UUID where " +
        "r.eventType='Creation' and t.eventType = 'Reception' and r.EVENT_UUID in ?1", isNative = true)
public List<EventT> findDeliveredCreatedEvents(List<String> eventIds);
1 голос
/ 05 марта 2013

Пробовал в JPA2 с Hibernate в качестве провайдера, и кажется, что Hibernate поддерживает получение списка "IN", и это работает.(По крайней мере для именованных запросов, и я полагаю, что это будет аналогично именованным запросам NATIVE.) Внутренний режим hibernate создает динамические параметры внутри IN, равные количеству элементов в переданном списке.

Вы пример выше

List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();

Если список содержит 2 элемента, запрос будет выглядеть как

select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?, ?)

, а если он имеет 3 элемента, он выглядит как

select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
         "where u.user_id in (?, ?, ?)
0 голосов
/ 29 июня 2018

в настоящее время я использую JPA 2.1 с Hibernate

Я также использую условие IN с собственным запросом.Пример моего запроса

SELECT ... WHERE table_name.id IN (?1)

Я заметил, что невозможно передать строку типа "id_1, id_2, id_3" из-за ограничений, описанных Джеймс

Но когда выиспользовать jpa 2.1 + hibernate можно передавать список строковых значений.Для моего случая действует следующий код:

    List<String> idList = new ArrayList<>();
    idList.add("344710");
    idList.add("574477");
    idList.add("508290");

    query.setParameter(1, idList);
0 голосов
/ 18 июля 2017

Вы можете попробовать это : userIdList вместо (? UserIdList)

@NamedNativeQuery(
       name="User.findByUserIdList", 
       query="select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
             "where u.user_id in :userIdList"
)
...