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 迁移问题的信息,请参阅: