Java 如何在JPQL或HQL中执行限制查询?
在Hibernate3中,有没有一种方法可以等效于HQL中的以下MySQL限制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中
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);