tarjeta - JPA pasando la lista a la cláusula IN en la consulta nativa nombrada
tarjeta mastercard banco nacion (7)
Sé que puedo pasar una lista a la consulta con nombre en JPA, pero ¿qué hay de NamedNativeQuery? He intentado de muchas maneras, pero aún no puedo pasar la lista a un NamedNativeQuery. ¿Alguien sabe cómo pasar una lista a la cláusula in en NamedNativeQuery? ¡Muchas gracias!
El NamedNativeQuery es el siguiente:
@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)"
)
y se llama así:
List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();
Sin embargo, el resultado no es como esperaba.
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
Actualmente utilizo JPA 2.1 con Hibernate.
También uso la condición IN con consulta nativa. Ejemplo de mi consulta
SELECT ... WHERE table_name.id IN (?1)
Noté que es imposible pasar String como "id_1, id_2, id_3" debido a las limitaciones descritas por
Pero cuando usas jpa 2.1 + hibernar es posible pasar la lista de valores de cadena. Para mi caso el siguiente código es válido:
List<String> idList = new ArrayList<>();
idList.add("344710");
idList.add("574477");
idList.add("508290");
query.setParameter(1, idList);
Dependiendo de su base de datos / proveedor / controlador / etc., puede, de hecho, pasar una lista como un parámetro enlazado a una consulta nativa JPA.
Por ejemplo, con Postgres y EclipseLink, lo siguiente funciona (devolviendo verdadero), demostrando matrices multidimensionales y cómo obtener una matriz de doble precisión. ( SELECT pg_type.* FROM pg_catalog.pg_type
para otros tipos; probablemente aquellos con _
, pero SELECT pg_type.* FROM pg_catalog.pg_type
antes de usarlo).
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();
La conversión está allí, por lo que la matriz literal es de dobles en lugar de numérica.
Más al punto de la pregunta: no sé cómo o si puede hacer consultas con nombre; Creo que depende, tal vez. Pero creo que seguir las cosas funcionaría para 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();
No tengo el mismo esquema que OP, así que no lo he comprobado exactamente, pero creo que debería funcionar, de nuevo, al menos en Postgres & EclipseLink.
Además, la clave se encontró en: http://tonaconsulting.com/postgres-and-multi-dimensions-arrays-in-jdbc/
Probé en JPA2 con Hibernate como proveedor y parece que hibernate admite la toma de una lista para "IN" y funciona. (Al menos para consultas con nombre y creo que será similar con las consultas NATIVAS con nombre) Lo que hibernación internamente genera parámetros dinámicos, dentro de la IN igual que el número de elementos en la lista aprobada.
Así que en tu ejemplo anterior
List<Object[]> userList = em.createNamedQuery("User.findByUserIdList").setParameter("userIdList", list).getResultList();
Si la lista tiene 2 elementos, la consulta se verá como
select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
"where u.user_id in (?, ?)
y si tiene 3 elementos parece
select u.user_id, u.dob, u.name, u.sex, u.address from user u "+
"where u.user_id in (?, ?, ?)
Puede intentar esto : userIdList en lugar de (? 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"
)
Una lista no es un parámetro válido para una consulta SQL nativa, ya que no se puede enlazar en JDBC. Debe tener un parámetro para cada argumento en la lista.
donde u.user_id en (? id1,? id2)
Esto se admite a través de JPQL, pero no de SQL, por lo que podría usar JPQL en lugar de una consulta nativa.
Algunos proveedores JPA pueden admitir esto, por lo que es posible que desee registrar un error con su proveedor.
Utilizando los datos de hibernación, JPA 2.1 y deltaspike, podría pasar una lista como parámetro en la consulta que contiene la cláusula IN. mi consulta es abajo
@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);
¡La respuesta aceptada anterior no es correcta y me sacó de la pista por muchos días!
JPA e Hibernate aceptan colecciones en consultas nativas utilizando Query.
Solo necesitas hacer
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);
También refiera las respuestas aquí que sugieren lo mismo (escogí el ejemplo anterior de uno de ellos)
- Referencia 1
- Referencia 2 que menciona en qué casos funciona la parántesis que da la lista como parámetro.