Validaţi sintaxa expresiei IN cu un parametru de intrare cu o colecţie de valori

Conform specificaţiei Java Persistence API (JPA) pentru expresiile IN, un parametru de intrare cu o colecţie de valori nu este înconjurat de paranteze. OpenJPA permite parantezelor să fie prezente, întrucât EclipseLink aruncă o excepţie când apelaţi metoda Query.setParameter cu un obiect colecţie care corespunde unui parametru de intrare IN cu o colecţie de valori încadrat de paranteze.

Această regulă detectează şiruri care conţin declaraţii Java Persistence Query Language (JPQL) cu expresii IN care au un singur parametru închis între paranteze. Deoarece şirul interogare şi apelul corespunzător la setParameter poate fi în clase diferite, regula nu poate garanta faptul că parametrul este o colecţie. Dacă parametrul este un tip de colectare, înlăturaţi parantezele din şirul interogare. Reţineţi că parantezele sunt valide pentru parametrii de intrare literali sau cu o singură valoare, aşa că fiţi atent ce înlăturaţi.

Această problemă este rezolvată prin înlăturarea parantezelor dintr-o expresie IN cu un parametru de intrare cu o colecţie de valori.

De exemplu, OpenJPA permite paranteze în şirurile interogare următoare, dar EclipseLink aruncă o excepţie când apelaţi setParameter şi încercaţi să setaţi ids la o valoare care este o colecţie.

  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);

Pentru a rezolva această problemă, înlăturaţi parantezele când ids reprezintă o colecţie.

  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);

În continuare, este prezentat un exemplu care este semnalat dar nu ar trebui să fie schimbat, deoarece id este un parametru cu o singură valoare.


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

Pentru informaţii despre această problemă şi alte probleme de migrare de la OpenJPA la EclipseLink, vedeţi: