Answers:
几年前,当有人问到为什么它在Hibernate 2中有效但在Hibernate 3中无效时,此消息发布在Hibernate论坛上:
在HQL中,从不支持Limit 子句。您应该使用setMaxResults()。
因此,如果它在Hibernate 2中工作,那似乎是巧合,而不是设计。我认为这是因为Hibernate 2 HQL解析器将替换它识别为HQL的查询的位,而其余部分保持不变,因此您可以使用一些本机SQL。但是,Hibernate 3具有适当的AST HQL解析器,并且它的宽容度要低得多。
我认为Query.setMaxResults()
确实是您唯一的选择。
setMaxResults
这将从结果集中获取有限数量的结果行并将其显示给用户,在我的情况下,我要查询300万条记录,然后调用setMaxResults进行设置50条记录,但我不想这样做,而查询本身我想查询50条记录,有没有办法做到这一点?
setMaxResults
冬眠会将limit
部分追加到查询。它不会获得所有结果。您可以通过以下方式检查它产生的查询:<property name="show_sql">true</property>
// SQL: SELECT * FROM table LIMIT start, maxRows;
Query q = session.createQuery("FROM table");
q.setFirstResult(start);
q.setMaxResults(maxRows);
setFirstResult
在这个答案,而这里其实是提到和其他地方,他们只是说setMaxResults
这个和setMaxResults
那个没有提及如何设置偏移。
如果您不想setMaxResults()
在Query
对象上使用,那么您总是可以恢复使用普通的SQL。
如果不想使用setMaxResults,也可以使用Query.scroll而不是list,并获取所需的行。例如,对于分页很有用。
setMaxResults()
首先将每个记录加载到内存中,然后创建一个子列表,当有数十万个或更多记录时,该子列表会使服务器崩溃,因为它内存不足。但是,我可以从JPA类型查询转到Hibernate查询QueryImpl hibernateQuery = query.unwrap(QueryImpl.class)
,然后可以scroll()
按照您的建议使用该方法。
setFirstResult
与setMaxResults
Query
方法对于JPA和Hibernate Query
,该setFirstResult
方法等效于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支持许多特定于数据库的分页选项:
现在,根据您使用的基础关系数据库系统,上面的JPQL查询将使用正确的分页语法。
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_ > ?
使用setFirstResult
和的优势setMaxResults
是Hibernate可以为任何受支持的关系数据库生成特定于数据库的分页语法。
并且,您不仅限于JPQL查询。您可以将setFirstResult
and setMaxResults
方法7用于本机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 ?
酷吧?
当您可以为过滤和排序条件建立索引时,分页很好。如果您的分页要求暗示动态过滤,那么使用诸如ElasticSearch之类的反向索引解决方案是一种更好的方法。
请查看本文以获取更多详细信息。
如果可以在此模式下管理限制
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();
}
这是处理限制或列表的非常简单的代码。
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());
}
您需要编写本机查询,请参考this。
@Query(value =
"SELECT * FROM user_metric UM WHERE UM.user_id = :userId AND UM.metric_id = :metricId LIMIT :limit", nativeQuery = true)
List<UserMetricValue> findTopNByUserIdAndMetricId(
@Param("userId") String userId, @Param("metricId") Long metricId,
@Param("limit") int limit);
您可以使用以下查询
NativeQuery<Object[]> query = session.createNativeQuery(select * from employee limit ?)
query.setparameter(1,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);
Hibernate-5.0.12
。这还不可用吗?要获得一百万个左右的记录,然后对其应用过滤器,setMaxResults
就像@Rachel在@skaffman的答案中所注意到的那样,这真的很沉重。