我使用EclipseLink作爲JPA實現,我需要使用主鍵(數字ID)獲取多個對象。但我也需要維護給定的id順序。JPA EclipseLink - 通過主鍵維護訂單獲取多個對象
使用本機MySQL的這種行爲可以使用ORDER BY FIELD
SELECT id FROM table WHERE id IN(9,5,2,6) ORDER BY FIELD(id,9,5,2,6);
我現在試圖複製使用JPA實施此查詢得到。從this thread已經建立,ORDER BY FIELD
不支持,所以我去了一個更低層次的方法使用JPA native query
。
我嘗試使用參數查詢來實現此目標,而不是使用原始語句。第一個實現是這樣
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();
正如你可以看到ORDER
條款現在還沒有,第一步,我只是想用ids
列表與IN
操作人員進行參數查詢工作。在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我使用?1
代替?
也試過,但沒有改變提供。有沒有辦法使nativeQuery
與ID列表工作?
就目前我使用的是完整的原始SQL語句
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();
但起初我開始與參數查詢,每次陳述解析的相關優化和性能。
編輯
隨着克里斯的建議,我嘗試使用FUNCTION
操作(這是可用,因爲我使用的是最新的EclipseLink
)一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)
我必須說,有一個元素代碼工作的名單,但有10種元素的另一個列表有錯誤
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)
看來,即使W/O括號,所產生的語句有他們
JPA本機查詢不支持集合,在這裏看到http://stackoverflow.com/questions/21484176/how-to-use-a-dynamic-parameter-in-a-in-子句的一個jpa命名查詢 – Guenther
有沒有辦法將它作爲字符串加入列表綁定之前傳遞它作爲參數? –