Validar a sintaxe de expressão IN com um parâmetro de entrada de valor de coleção

A especificação da API de Persistência Java (JPA) para expressões IN define que um parâmetro de entrada de valor de coleção não seja colocado entre parênteses. O OpenJPA permite a presença de parênteses, enquanto o EclipseLink lança uma exceção ao chamar o método Query.setParameter com um objeto de coleção correspondente a um parâmetro de entrada de valor de coleção IN entre parênteses.

Essa regra detecta sequências contendo instruções Java Persistence Query Language (JPQL) com expressões IN que possuem um único parâmetro colocado entre parênteses. Como a sequência de consultas e a chamada correspondente para setParameter podem estar em classes diferentes, a regra não pode garantir que o parâmetro é uma coleção. Se o parâmetro for um tipo de coleção, remova os parênteses da sequência de consultas. Observe que parênteses são válidos para literais ou parâmetros de entrada com único valor; por isso, tenha cuidado com aquilo que você remove.

Esse problema é resolvido removendo os parênteses de uma expressão IN com um parâmetro de entrada de valor de coleção.

Por exemplo, o OpenJPA permitirá os parênteses nas sequências de consultas a seguir, mas o EclipseLink lançará uma exceção quando você chamar setParameter e tentar configurar ids para um valor que é uma coleção.

  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 corrigir esse problema, remova os parênteses quando ids representar uma coleção.

  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 seguir é mostrado um exemplo que é sinalizado, mas não deve ser mudado porque id é um parâmetro de valor único.


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

Para obter informações sobre esse problema e outros problemas de migração de OpenJPA para EclipseLink, veja: