2016-09-15 3 views
0

저는 JPA 구현으로 EclipseLink를 사용하고 있으며 기본 키 (숫자 ID)를 사용하여 여러 객체를 가져와야합니다. 하지만 주어진 id 순서를 유지해야합니다.JPA EclipseLink - 기본 키 유지 보수 순서로 여러 객체 가져 오기

기본 MySQL의에게 행동 이런 종류의 사용은 지금 JPA 구현을 사용하여이 쿼리를 복제하기 위해 노력하고있어 ORDER BY FIELD

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

사용하여 얻을 수 있습니다. 이미 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 개 ID는 내가 대신 ??1를 사용하여 시도 쿼리 this topic에서

,하지만 변화에 제공되었다. 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 문을 사용하고 순간

.


크리스의 제안으로

편집 나는 (I 최신 EclipseLink을 사용하고 있기 때문에 볼 수 있습니다)에 FUNCTION 연산자를 사용하여 TypedQuery을 시도했다.이 코드

EDIT 2

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, ?)") 

는 괄호없이 시도를 수행하지만, 여전히 에러

이 있지만 여기에 오차 결과 코드

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 개 요소의 또 다른 목록 그것도 괄호 O/W 결과 문

그들을 것 같다 오류

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)"가 EclipseLink에서 작동하는 "Entity e에서 전자를 선택하십시오.

누락 된 비트는 '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 호출의 목록이 작동하지 않습니다. 이 문제와 관련된 버그를 찾았습니까? 나는 무언가를 찾으려고했지만 어떤 결과도 얻지 못했습니다. –