验证带有集合值输入参数的 IN 表达式语法

IN 表达式的 Java 持久性 API (JPA) 规范定义了集合值输入参数不用括号括起。当您使用某个集合对象调用 Query.setParameter 方法,并且该集合对象所对应的 IN 集合值输入参数用括号括起时,OpenJPA 允许存在括号,而 EclipseLink 将抛出异常。

该规则会检测满足以下条件的字符串:包含带有 IN 表达式的 Java 持久性 Query Language (JPQL) 语句,且这些表达式中包含用括号括起的单个参数。 因为查询字符串和 setParameter 的对应调用可能位于不同类中,所以该规则无法保证该参数是一个集合。 如果参数是集合类型,那么从查询字符串移除括号。请注意,括号对于字面值或单值输入参数有效,因此请小心移除内容。

该问题可通过从带有集合值输入参数的 IN 表达式移除括号来解决。

例如,OpenJPA 允许在以下查询字符串中使用括号,但当您调用 setParameter 并尝试将 ids 设置为集合值时,EclipseLink 会抛出异常。

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

要修复该问题,请在 ids 代表集合时移除括号。

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

下面显示了一个已被标记但不可更改的示例,因为 id 是单值参数。


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

有关该问题和其他的 OpenJPA 到 EclipseLink 迁移问题的信息,请参阅: