你如何在HQL中进行限制查询?

时间:2009-08-06 15:33:22

标签: java hibernate hql hibernate3

在Hibernate 3中,有没有办法在HQL中执行以下MySQL限制?

select * from a_table order by a_table_column desc limit 0, 20;

如果可能,我不想使用setMaxResults。这在旧版本的Hibernate / HQL中肯定是可能的,但似乎已经消失了。

14 个答案:

答案 0 :(得分:289)

几年前Hibernate论坛上的

This was posted被问及为什么这在Hibernate 2中有效但在Hibernate 3中没有用:

  

限制从不受支持的条款   在HQL中。你打算用   setMaxResults()。

因此,如果它在Hibernate 2中有效,那似乎是巧合,而不是设计。我认为这是因为Hibernate 2 HQL解析器会替换它识别为HQL的查询位,并保留其余部分,因此您可以隐藏一些本机SQL。然而,Hibernate 3有一个适当的AST HQL Parser,它的宽容度要低得多。

我认为Query.setMaxResults()确实是你唯一的选择。

答案 1 :(得分:135)

 // SQL: SELECT * FROM table LIMIT start, maxRows;

Query q = session.createQuery("FROM table");
q.setFirstResult(start);
q.setMaxResults(maxRows);

答案 2 :(得分:18)

如果您不想在setMaxResults()对象上使用Query,则可以始终恢复使用普通SQL。

答案 3 :(得分:5)

如果您不想使用setMaxResults,也可以使用Query.scroll而不是list,并获取所需的行。例如,用于分页。

答案 4 :(得分:5)

由于这是一个非常常见的问题,所以我写了 this article,此答案基于此。

setFirstResultsetMaxResults Query方法

对于JPA和Hibernate QuerysetFirstResult方法等效于OFFSET,而setMaxResults方法等效于LIMIT:

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();

LimitHandler抽象

Hibernate LimitHandler定义了特定于数据库的分页逻辑,如下图所示,Hibernate支持许多特定于数据库的分页选项:

<code>LimitHandler</code> implementations

现在,根据所使用的基础关系数据库系统,上述JPQL查询将使用正确的分页语法。

MySQL

SELECT p.id AS id1_0_,
       p.created_on AS created_2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?, ?

PostgreSQL

SELECT p.id AS id1_0_,
       p.created_on AS created_2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?

SQL Server

SELECT p.id AS id1_0_,
       p.created_on AS created_on2_0_,
       p.title AS title3_0_
FROM post p
ORDER BY p.created_on
OFFSET ? ROWS 
FETCH NEXT ? ROWS ONLY

Oracle

SELECT *
FROM (
    SELECT 
        row_.*, rownum rownum_
    FROM (
        SELECT 
            p.id AS id1_0_,
            p.created_on AS created_on2_0_,
            p.title AS title3_0_
        FROM post p
        ORDER BY p.created_on
    ) row_
    WHERE rownum <= ?
)
WHERE rownum_ > ?

使用setFirstResultsetMaxResults的优点是Hibernate可以为任何受支持的关系数据库生成特定于数据库的分页语法。

而且,您不仅限于JPQL查询。您可以将setFirstResultsetMaxResults方法七用于本机SQL查询。

本地SQL查询

使用本机SQL查询时,不必对特定于数据库的分页进行硬编码。 Hibernate可以将其添加到您的查询中。

因此,如果您要在PostgreSQL上执行此SQL查询:

List<Tuple> posts = entityManager
.createNativeQuery(
    "SELECT " +
    "   p.id AS id, " +
    "   p.title AS title " +
    "from post p " +
    "ORDER BY p.created_on", Tuple.class)
.setFirstResult(10)
.setMaxResults(10)
.getResultList();

Hibernate将对其进行如下转换:

SELECT p.id AS id,
       p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?

很酷,对吧?

超越基于SQL的分页

当您可以为过滤和排序条件建立索引时,分页效果很好。如果您的分页需求要求动态过滤,那么使用诸如ElasticSearch之类的反向索引解决方案是一种更好的方法。

查看this article了解更多详细信息。

答案 5 :(得分:3)

String hql = "select userName from AccountInfo order by points desc 5";

这对我有用,而不使用setmaxResults();

只需提供最后一个(在这种情况下为5)的最大值,而不使用关键字limit。 :P

答案 6 :(得分:1)

我的观察是,即使你在HQL(hibernate 3.x)中有限制,它也会导致解析错误或者被忽略。 (如果你在限制之前通过+ desc / asc订购,它将被忽略,如果你在限制之前没有desc / asc,它将导致解析错误)

答案 7 :(得分:1)

如果可以在此模式下管理限制

public List<ExampleModel> listExampleModel() {
    return listExampleModel(null, null);
}

public List<ExampleModel> listExampleModel(Integer first, Integer count) {
    Query tmp = getSession().createQuery("from ExampleModel");

    if (first != null)
        tmp.setFirstResult(first);
    if (count != null)
        tmp.setMaxResults(count);

    return (List<ExampleModel>)tmp.list();
}

这是一个非常简单的代码来处理限制或列表。

答案 8 :(得分:1)

@Query(nativeQuery = true,
       value = "select from otp u where u.email =:email order by u.dateTime desc limit 1")
public List<otp> findOtp(@Param("email") String email);

答案 9 :(得分:0)

Criteria criteria=curdSession.createCriteria(DTOCLASS.class).addOrder(Order.desc("feild_name"));
                criteria.setMaxResults(3);
                List<DTOCLASS> users = (List<DTOCLASS>) criteria.list();
for (DTOCLASS user : users) {
                System.out.println(user.getStart());
            }

答案 10 :(得分:0)

您需要编写原生查询,请参阅this

ngOninit()
{
    this._route.params.
    subscribe(params => 
    {
       this.changeLanguage(params[":lang"]);
       //Any incoming parameter must be sanitized for obvious reasons.
    }
}

changeLanguage(language)
{
    //change language logic here
}

答案 11 :(得分:0)

您可以轻松地使用分页。

    @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value = "true") })
    @Query("select * from a_table order by a_table_column desc")
    List<String> getStringValue(Pageable pageable);

您必须通过new PageRequest(0, 1)才能获取记录,并从列表中获取第一条记录。

答案 12 :(得分:0)

您可以使用以下查询

NativeQuery<Object[]> query = session.createNativeQuery(select * from employee limit ?)
query.setparameter(1,1);

答案 13 :(得分:0)

下面的代码段用于使用HQL执行限制查询。

Query query = session.createQuery("....");
query.setFirstResult(startPosition);
query.setMaxResults(maxRows);

您可以在此link上获得演示应用程序。