Validar la sintaxis de expresión IN con un parámetro de entrada de colección con valores

La especificación de JPA (Java Persistence API) para expresiones IN define que un parámetro de entrada de valor de colección no está entre paréntesis. OpenJPA permite que el paréntesis esté presente, mientras que EclipseLink emite una excepción cuando se llama al método Query.setParameter con un objeto de colección correspondiente a un parámetro de entrada de valor de colección IN entre paréntesis.

Esta regla detecta series que contienen sentencias JPQL (Java Persistence Query Language) con expresiones IN que tienen un único parámetro entre paréntesis. Puesto que la serie de consulta y la llamada correspondiente a setParameter pueden estar en clases diferentes, la regla no puede garantizar que el parámetro es una colección. Si el parámetro es un tipo de colección, elimine los paréntesis de la serie de consulta. Tenga en cuenta que los paréntesis son válidos para literales o parámetros de entrada de un solo valor, por lo que debe tener cuidado con lo que elimina.

Este problema se resuelve eliminando los paréntesis de una expresión IN con un parámetro de entrada de valor de colección.

Por ejemplo, OpenJPA permite los paréntesis en las siguientes series de consulta, pero EclipseLink emite una excepción cuando se llama a setParameter y se intenta establecer ids en un valor que es una colección.

  List<String> idList = getIdsToQuery();
  Query query = em.createQuery("SELECT p FROM Person p WHERE p.id IN (:ids)");
  query.setParameter("ids", idList);
  
  final String ENTITY_NAME = "Person";
  final String PRIMARY_KEY = "id";
  List<String> idList2 = getIdsToQuery();
  Query query = em.createQuery("SELECT p FROM " + ENTITY_NAME + " p " +" WHERE p." + PRIMARY_KEY + " IN (:ids)");
  query.setParameter("ids", idList2);

Para corregir este problema, elimine el paréntesis cuando ids representa una colección.

  List<String> idList = getIdsToQuery();
  Query query = em.createQuery("SELECT p FROM Person p WHERE p.id IN :ids");
  query.setParameter("ids", idList);
  
  final String ENTITY_NAME = "Person";
  final String PRIMARY_KEY = "id";
  List<String> idList2 = getIdsToQuery();
  Query query = em.createQuery("SELECT p FROM " + ENTITY_NAME + " p " +" WHERE p." + PRIMARY_KEY + " IN :ids");
  query.setParameter("ids", idList2);

A continuación se muestra un ejemplo que está marcado, pero que no se debe cambiar porque id es un parámetro de un solo valor.


  String idMatch = getIdToQuery();
  Query query = em.createQuery(SELECT p FROM Person p WHERE p.id IN (:id));
  query.setParameter("id", idMatch);
  

Si desea más información sobre este problema y otros problemas de migración de OpenJPA a EclipseLink, consulte: