我使用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
有没有办法将它作为字符串加入列表绑定之前传递它作为参数? –