2016-09-15 10 views
0

私はJPA実装としてEclipseLinkを使用しています。プライマリ・キー(数値ID)を使用して複数のオブジェクトを取得する必要があります。しかし、私はまた、指定されたid順序を維持する必要があります。JPA EclipseLink - プライマリ・キーの保守順序で複数のオブジェクトを取得

行動のこの種のは、私は今、JPAの実装を使用して、このクエリを複製しようとしているORDER BY FIELD

SELECT id FROM table WHERE id IN(9,5,2,6) ORDER BY FIELD(id,9,5,2,6); 

を使用して得ることができるネイティブのMySQLを使用して。既にthis threadから確立されているように、ORDER BY FIELDはサポートされていませんので、私はJPA native queryを使用して、より低レベルのアプローチに行きました。

未処理のステートメントを使用する代わりに、パラメータクエリを使用してこの目標に到達しようとしています。あなたは、私はちょうどINオペレータとidsリストを使用してパラメータクエリの仕事をしようとして最初のステップのために、ORDER句はまだありません見ることができるように最初の実装は、この

Class<?> clazz = ...; 
List<Long> ids = ...; 

EntityManagerFactory emf = ...; 
EntityManager em = emf.createEntityManager(); 
String statement = "SELECT * FROM table WHERE id IN (?)"; 

Query createNativeQuery = em.createNativeQuery(statement, clazz); 
createNativeQuery.setParameter(1, ids); 
List resultList = createNativeQuery.getResultList(); 

のようでした。 setParameterメソッドでは、Listオブジェクトをコンマで区切ったリスト(文字列として)を提供しようとしましたが、どれも機能しませんでした。最後には、すべてSQL構文エラーで終了します。 また、かっこでかっこを使って試してみましたが、何も効果がありません。

は、ここではいくつかのテストでは、私はすべてのエラーを与えるものではありません

String statement = "SELECT * FROM " + tableName + " WHERE id IN (?)"; 
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject()); 
createNativeQuery.setParameter(1, ids); 

問い合わせをしたが、何の結果が与えられていません。

String statement = "SELECT * FROM " + tableName + " WHERE id IN (?)"; 
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject()); 
createNativeQuery.setParameter(1, Joiner.on(",").join(ids)); 

つのみ結果が与えられていないが、7つのIDSはthis topicからクエリ

に設けられたIも?1代わりに?を用いて試みたが、何も変更。 nativeQueryにIDのリストを使用させる方法はありますか?

私は

String joinedId = Joiner.on(",").join(ids); 
String statement = "SELECT * FROM " + tableName + " WHERE id IN (" + joinedId + ") ORDER BY FIELD(id," + joinedId + ")"; 
Query createNativeQuery = emJpa.createNativeQuery(statement, this.em.getClassObject()); 
createNativeQuery.getResultList(); 

をフル生のSQL文を使用していた瞬間のためではなく、最初に、私はたびに文を解析するのに関連する最適化およびパフォーマンスのためのパラメータクエリで開始。


EDIT

クリスの提案で私は(私は最新のEclipseLinkを使用しているので、入手可能です)FUNCTION演算子を使用してTypedQueryを試してみました。ここで

Local Exception Stack: 
Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: java.sql.SQLException: Operand should contain 1 column(s) 
Error Code: 1241 
Call: SELECT ... all the fields ... FROM webcontent_type WHERE (ID IN ((?,?,?,?,?,?,?))) ORDER BY FIELD(ID, (?,?,?,?,?,?,?)) 
    bind => [14 parameters bound] 
Query: ReadAllQuery(referenceClass=WebContentType sql="SELECT ... all the fields ... FROM webcontent_type WHERE (ID IN (?)) ORDER BY FIELD(ID, ?)") 

EDIT括弧なしにしようとしました2

このコードを実行しながら、結果のコード

List<Long> ids = ...; 
Class<?> clazz = ...; 
String statement = "SELECT e FROM " + clazz.getSimpleName() + " e WHERE e.id IN (:idList) ORDER BY FUNCTION('FIELD', e.id, :idList)"; 

EntityManagerFactory emf = ...; 
EntityManager em = emf.createEntityManager(); 

TypedQuery<?> query = em.createQuery(statement, clazz); 
query.setParameter("idList", ids); 

List resultList = query.getResultList(); 

そして、ここではエラーがあるですが、エラーが依然として存在する

SELECT e FROM FrameWorkUser e WHERE e.id IN :idList ORDER BY FUNCTION('FIELD', e.id, :idList) 

私は1つの要素のリストでコードが動作すると言わなければならないが、10個の要素の別のリストとそれもW/O括弧と思われるエラー

javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.3.v20160428-59c81c5): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: java.sql.SQLException: Operand should contain 1 column(s) 
Error Code: 1241 
Call: SELECT .... FROM webcontent_type WHERE (ID IN (?,?,?,?,?,?,?)) ORDER BY FIELD(ID, (?,?,?,?,?,?,?)) 
    bind => [14 parameters bound] 
Query: ReadAllQuery(referenceClass=WebContentType sql="SELECT .... FROM webcontent_type WHERE (ID IN ?) ORDER BY FIELD(ID, ?)") 
    at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:382) 
    at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260) 
    at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:473) 

があり、結果の文は、それらを持っている

+0

JPAネイティブクエリは、コレクションをサポートしていない、ここhttp://stackoverflow.com/questions/21484176/how-to-use-a-dynamic-parameter-in-a-in-を参照してください:何かのように句のjpa名前付きクエリ – Guenther

+0

パラメータとして渡す前に、リストを文字列として結合する方法はありますか? –

答えて

1

ネイティブクエリを使用する場合は、データベースのSQLを形成するのとまったく同じようにする必要があります。つまり、JPAプロバイダはSQLを変更する予定がないため、リストをコンポーネントパラメータに分割する必要があります。君は。ほとんどのプロバイダはJPQLのリストを処理します。したがって、 "e.id in:(idlist)のEntity eからselect e"をEclipseLinkで使用できます。

あなたの欠けているビットは、 'FIELD'がJPQL構成ではないことです。このためには、JPQL 2.1 FUNCTION演算子を使用する必要があります。

"Select e from Entity e where e.id in :idList order by FUNCTION('FIELD', e.id, :idList)" 
+0

あなたが提案したコードを試しました(私は 'FUNCTION'節について知らなかった)。あなたは主な質問の結果を読むことができます。私は新しいセクションの下に新しいセクション –

+0

を追加しました。私は間違いを訂正しました。少し答えを修正しました。あなたのJPQLで()を使わないでください。それはちょうど "in:idList"でなければなりません。 FUNCTIONコールのリストを分解しなければならないかもしれません。あるいは、EclipseLinkの呼び出しを見て、問題を修正するために少し見てください。私はソースをもう使用しないので、バグを調べることをお勧めします回避策があるかどうかを確認してください。 – Chris

+0

括弧を削除しましたが、同じエラーがあります(主な質問のEDIT2を参照)。提案したように、FUNCTION呼び出しのリストは機能しません。この問題に関連するバグを見つけましたか?私は何かを見つけようとしましたが、結果はありません –

関連する問題