Ověřit syntaxi výrazu IN se vstupním parametrem s hodnotou kolekce

Specifikace JPA (Java Persistence API) pro výrazy IN definuje, že vstupní parametr s hodnotou kolekce není uzavřený do závorek. Rozhraní OpenJPA připouští závorky, zatímco EclipseLink generuje výjimku při volání metody Query.setParameter s objektem kolekce odpovídajícím vstupnímu parametru s hodnotou kolekce IN v závorkách.

Toto pravidlo zjistí řetězce obsahující příkazy jazyka JPQL (Java Persistence Query Language) s výrazy IN, které mají jeden parametr uzavřený do závorek. Protože řetězec dotazu a odpovídající volání metody setParameter mohou být v různých třídách, pravidlo nemůže zaručit, že daný parametr je kolekce. Je-li parametr typ kolekce, odeberte závorky z řetězce dotazu. Všimněte si, že závorky jsou platné pro literály nebo jednohodnotové vstupní parametry, takže buďte opatrní při tom, co odeberete.

Tento problém se vyřeší odebráním závorek z výrazu IN se vstupním parametrem s hodnotou kolekce.

Například OpenJPA umožňuje závorky v následujících řetězcích dotazů, ale EclipseLink generuje výjimku při volání setParameter a pokusí se nastavit parametr ids na hodnotu, která je kolekcí.

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

Chcete-li tento problém opravit, odeberte závorky, když parametr ids představuje kolekci.

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

Dále je uveden příklad, který je označen, ale neměl by být změněn, protože id je jednohodnotový parametr.


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

Informace o tomto problému a jiných problémech migrace OpenJPA na EclipseLink viz: