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のコレクションがほとんど含まれていない場合があるため、これを行うのはそれほど簡単ではありません。

4

2 に答える 2

2

簡単な答えは次のとおりです。INクエリを使用する場合、空の配列/リストを使用してパラメータとして設定することはできません。文字列の集中を使用してクエリを作成する場合があります。リストが空の場合/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をバインドしてみてください。

.. in(:arg)

または、nullを含むリストを渡します

.. in:list

于 2012-10-09T14:04:04.660 に答える