带参数的JPQL ORDER BY子句

21

我正在尝试编写带有ORDER BY子句的JPQL查询:

query = "SELECT c FROM item ORDER BY c.name ASC"

我想设置一个名为"order"的参数,其值可以是"ASC"或"DESC"。

query = "SELECT c FROM item ORDER BY c.name :order"

然后在我的实现中:

query.setParameter("order", "ASC");

这是我遇到Hibernate错误时的情况:

org.hibernate.HibernateException: Errors in named queries

有什么想法,我在做错了什么吗?谢谢!

4个回答

25

“ASC”或“DESC”不能作为查询参数。相反,您可以使用字符串连接。

query = "SELECT c FROM item ORDER BY c.name " + sortOrder;

您应该验证 sortOrder 的内容只能是 ASC 或 DESC,而且不能直接来自用户。


1
好的,这解释了很多问题。在@NamedQuery的声明中有没有使用字符串连接的方法? - Pierre Duplouy

9
如果您想在此处使用命名查询,则需要两个(命名查询是静态的,不能像@Mark所指出的那样使用ASC和DESC作为参数)。

或者我可以使用动态查询? - Pierre Duplouy
@Pedro 当然可以。但这不会是一个@NamedQuery(我实际上是在回答你的评论之一)。 - Pascal Thivent
你说得对。但事实是,我有很多需要排序的命名查询,因此为每个查询创建2个将导致命名查询增加一倍。这是一个问题吗?还是应该改用动态查询? - Pierre Duplouy
从维护的角度来看,使用动态查询肯定会更好。这就是我会做的事情。 - Pascal Thivent

6

不需要写两次包含“order by”子句的命名查询,您可以按照以下方式实现DAO:

public List<MyEntity> findByAttribute(boolean desc,...){
    TypedQuery<MyEntity> q = em.createNamedQuery(...
    q.setParameter(...
    List<MyEntity> result = q.getResultList();
    if(desc){
        Collections.reverse(result );
    }
    return result;
}

7
如果使用了“分页”的功能,这可能就不适用了。 - Jin Kwon
1
只是想提醒一下,如果可能的话最好在数据库中进行排序,而不是在代码中进行。 - karol

1

我认为正确的方式是使用Criteria API的ORDER BY子句

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Country> q = cb.createQuery(Country.class);
Root<Country> c = q.from(Country.class);
q.select(c);
q.orderBy(cb.asc(c.get("currency")), cb.desc(c.get("population")));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接