Java 如何在JPQL或HQL中执行限制查询?

Java 如何在JPQL或HQL中执行限制查询?,java,hibernate,hql,hibernate3,Java,Hibernate,Hql,Hibernate3,在Hibernate3中,有没有一种方法可以等效于HQL中的以下MySQL限制 select * from a_table order by a_table_column desc limit 0, 20; 如果可能的话,我不想使用setMaxResults。这在旧版本的Hibernate/HQL中是完全可能的,但它似乎已经消失了。如果您不想使用setMaxResults()在查询对象上,您可以随时恢复使用普通SQL。几年前在Hibernate论坛上,当被问及为什么这在Hibernate 2中

在Hibernate3中,有没有一种方法可以等效于HQL中的以下MySQL限制

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

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

如果您不想使用
setMaxResults()
查询
对象上,您可以随时恢复使用普通SQL。

几年前在Hibernate论坛上,当被问及为什么这在Hibernate 2中有效而在Hibernate 3中无效时:

限制从来都不是一个受支持的条款 在HQL中。你注定要使用它 setMaxResults()

因此,如果它在Hibernate2中工作,那么这似乎是巧合,而不是设计。我认为这是因为Hibernate 2 HQL解析器将替换它识别为HQL的查询位,并保持其余部分不变,因此您可以潜入一些本机SQL。然而,Hibernate3有一个合适的ASTHQL解析器,它的宽容性要差得多


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

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

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

String hql=“从AccountInfo按点数desc 5选择用户名”

这在不使用
setmaxResults()的情况下对我有效

只需提供最后一个(在本例中为5)中的最大值,而不使用关键字
limit

:P

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

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();
}
公共列表listExampleModel(){ 返回listExampleModel(null,null); } 公共列表listExampleModel(整数优先,整数计数){ Query tmp=getSession().createQuery(“来自ExampleModel”); 如果(第一个!=null) tmp.setFirstResult(第一); 如果(计数!=null) tmp.setMaxResults(计数); return(List)tmp.List(); }
这是一个处理限制或列表的非常简单的代码

Criteria=curdSession.createCriteria(DTOCLASS.class).addOrder(Order.desc(“feild_name”);
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());
            }
标准:setMaxResults(3); 列表用户=(列表)条件。列表(); for(DTOCLASS用户:用户){ System.out.println(user.getStart()); }
您需要编写本机查询,请参阅

@Query(值=
“从user\u metric UM中选择*,其中UM.user\u id=:userId和UM.metric\u id=:metricId LIMIT:LIMIT”,nativeQuery=true)
列出FindTopnByUserAndMetricId(
@Param(“userId”)字符串userId,@Param(“metricId”)长metricId,
@参数(“限制”)整数限制);
@Query(nativeQuery=true,
value=“从otp u中选择,其中u.email=:按u.dateTime desc limit 1发送电子邮件订单”)
公共列表findOtp(@Param(“email”)字符串email);

您可以轻松地为此使用分页

    @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value = "true") })
    @Query("select * from a_table order by a_table_column desc")
    List<String> getStringValue(Pageable pageable);
@QueryHints({@QueryHint(name=“org.hibernate.cacheable”,value=“true”)})
@查询(“按表格列描述从表格顺序中选择*)
列表getStringValue(可分页可分页);
您必须通过
new PageRequest(0,1)
来获取记录,并从列表中获取第一条记录。

使用
setFirstResult
setMaxResults
查询方法
对于JPA和Hibernate
查询
setFirstResult
方法相当于
OFFSET
,而
setMaxResults
方法相当于LIMIT:

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "order by p.createdOn ")
.setFirstResult(10)
.setMaxResults(10)
.getResultList();
PostgreSQL SQL Server 神谕 Hibernate将对其进行如下转换:

SELECT p.id AS id,
       p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
很酷,对吧

超越基于SQL的分页
当您可以为筛选和排序条件编制索引时,分页是很好的。如果您的分页要求意味着动态筛选,那么使用反向索引解决方案(如ElasticSearch)是一种更好的方法。

您可以使用下面的查询

NativeQuery<Object[]> query = session.createNativeQuery(select * from employee limit ?)
query.setparameter(1,1);
NativeQuery query=session.createNativeQuery(从员工限额中选择*)
query.setparameter(1,1);

下面的代码片段用于使用HQL执行限额查询

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

您可以在这里获得演示应用程序。

这并不是很令人兴奋。我也不觉得HQL令人兴奋。为什么不在DB服务器上编写一个应用该限制的视图,然后让HQL查看该视图:PIt只是其中之一,虽然对于每个查询,SQL都比HQL容易得多,但创建视图和编写本机SQL对于重构来说并不太好。我会尽量避免。真正的问题是,无论如何,我把MySQL查询写错了,认为setMaxResults很奇怪。事实并非如此。如果您尝试在不同的DBMS供应商之间切换,痛苦正在等待着您。我没有使用limit,而是使用pageable来避免额外的数据,我认为Hibernate 3的方法更正确。你对Hibernate的使用是不可知数据库的,所以你应该以抽象的方式来做这类事情。我同意,但是当像这样的功能被删除时,迁移是一件非常痛苦的事情。但是对于setMaxResults,首先运行查询,然后在您调用的resultset上运行
setMaxResults
,这将从resultset中获取有限数量的结果行并将其显示给用户,在我的例子中,我有300万条被查询的记录,然后调用setMaxResults来设置50条记录,但我不想这样做,虽然查询本身,但我想查询50条记录,有没有办法做到这一点?我知道这是一篇老文章。我完全同意雷切尔的看法。我最近使用NHibernate(.Net-port of Hibernate)从2升级到了3,同样的,top X现在抛出了一个解析器错误。但是,当我在查询中添加setMaxResults时,它确实在生成的SQL中生成了一个TOP X(使用MSSQL2008dial)。“这很好,”瑞秋说
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 ?, ?
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 ?
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
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_ > ?
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();
SELECT p.id AS id,
       p.title AS title
FROM post p
ORDER BY p.created_on
LIMIT ?
OFFSET ?
NativeQuery<Object[]> query = session.createNativeQuery(select * from employee limit ?)
query.setparameter(1,1);
Query query = session.createQuery("....");
query.setFirstResult(startPosition);
query.setMaxResults(maxRows);