4

有没有办法在 IN 运算符中使用空集合?

List<Integer> idList = new ArrayList<Integer>();
Query query = em.createQuery("SELECT e FROM T e WHERE e.id IN ?1").setParameter(1, idList);
List results = query.getResultList();

产生:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
  Position: 48
Error Code: 0
Call: SELECT id, other_id FROM t_table WHERE (id IN ())
Query: ReadAllQuery(referenceClass=T sql="SELECT id, other_id FROM t_table WHERE (id IN ?)")

这个:

List<Integer> idList = new ArrayList<Integer>();

CriteriaBuilder cb = EntityManagerProvider.getEmf().getCriteriaBuilder();
CriteriaQuery<T> c = cb.createQuery(T.class);
Root<T> t_class = c.from(T.class);
Expression<String> exp = t_class.get("id");
Predicate predicate = exp.in(idList);

c.select(t_class).where(predicate);

TypedQuery<T> q = em.createQuery(c);
List results = q.getResultList();   

产生:

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near ")"
  Position: 48
Error Code: 0
Call: SELECT id, other_id FROM t_table WHERE (id IN ())
Query: ReadAllQuery(referenceClass=T sql="SELECT id, other_id FROM t_table WHERE (id IN ())")       

在 IN 中明确放置 null:

Query query = em.createQuery("SELECT e FROM T e WHERE e.id IN (null)");

产生:

    java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager: 
Exception Description: Syntax error parsing the query [SELECT e FROM T e WHERE e.id IN (null)], line 1, column 33: unexpected token [null].
Internal Exception: NoViableAltException(54@[709:9: (itemNode= scalarOrSubSelectExpression ( COMMA itemNode= scalarOrSubSelectExpression )* | subqueryNode= subquery )])

但是,使用本机查询可以正常工作:

List<Integer> idList = new ArrayList<Integer>();
Query query = em.createNativeQuery("SELECT * FROM t_table WHERE t_table.id IN (null)");
List results = query.getResultList();   

显然,我不想使用本机查询。当然,我可以在创建查询之前进行 if-else 检查,并为空集合创建不同的查询,或者在大多数情况下根本不创建它,因为在简单查询中不会有任何结果。但是我必须在大型项目中将供应商从 OpenJPA(接受空集合)更改为 EclipseLink,并且有时查询在不同的 IN 中包含很少的集合,所以 if-elsing 这不会那么容易。

4

2 回答 2

2

简单的答案是:在使用 IN 查询时,您不能使用空的 Array/List 并将其设置为 Parameter。您可以使用字符串浓度构建查询,如果列表为空 / size() == 0,则不要将 IN 部分添加到查询字符串中,也不要设置参数。

如果 IN 参数中有一个空集合,则结果查询没有什么不同,那么您可以删除此条件。除了你的目标真的是找不到任何结果。但是,从逻辑上讲,您可以在执行查询之前捕捉到这一点,原因在您的示例中:

“SELECT * FROM t_table WHERE t_table.id IN (null)”

=>这可能需要:a)所有结果都是有效的=>然后你可以简单地删除where条件b)没有结果是有效的=>那么你不需要执行查询并且可以只返回一个空的t_table列表在你的方法中。

塞巴斯蒂安

于 2012-10-08T13:16:54.347 回答
0

尝试 2.4 版本。

另外,尝试绑定null,

.. 在 (:arg)

或传递一个包含 null 的列表

.. 在:列表中

于 2012-10-09T14:04:04.660 回答