了解 Hibernate 的 Criteria#setMaxResults

2022-09-04 08:00:39

文档说:

Criteria setMaxResults(int maxResults)
>Set a limit upon the number of objects to be retrieved.

假设我有以下内容:Criteria

Criteria criteria = createCriteria(); // creates criteria for MY_TABLE entity
criteria.list().length; // let's say there's a million records in this table

添加将只返回一行吗?或者,它是否仍会返回 100 万行,但请选择其中之一?criteria.setMaxResults(1)

当对我的Oracle数据库运行类似于我上面的代码示例的查询时,我看到正在生成SQL。... ROWNUM < 2

但是,当我查看ROWNUM常见问题解答时,我不明白是在检索记录之前还是之后应用。我希望“之前”是有效的,而“之后”则不适用于大型结果集。ROWNUM

在从数据库中选择记录之后和执行 ORDER BY 子句之前,将评估 ROWNUM。


答案 1

添加 criteria.setMaxResults(1) 是否只返回一行?或者,它是否仍会返回 100 万行,但请选择其中之一?

是的,它只会返回一行,休眠使用数据库特定的功能来限制结果。休眠不会拾取 100 万行,但 db 会,然后选择第一行(此语句是关于休眠生成的查询,而不是 )。ROWNUM

假设您有一个名为 的表,其中有 8 行。user

+----+-----------+-------+
| id |   name    | score |
+----+-----------+-------+
|  1 | Xyz       |   500 |
|  2 | Name3     |   200 |
|  3 | Name2     |   300 |
|  4 | Name4     |   100 |
|  5 | SomeName  |   600 |
|  6 | BSomeName |   150 |
|  7 | Asomename |    80 |
|  8 | Csomename |   700 |
+----+-----------+-------+

现在,您运行以下条件。

criteria.add(Restriction.le("score", 500));
criteria.addOrder(Order.asc("name"));
criteria.setMaxResults(2);

以下由 Hibernate 生成的查询。

select * from(select * from user where score <= 500 order by name) where ROWNUM < 3; 

DB 将按以下顺序执行它。

  • 查找分数小于或等于 500 的所有行。在这里,它将找到6行。
  • 按名称按升序对所有行进行排序。
  • 分配给每一行。ROWNUM
  • 查找所有小于 3 的行并返回它们。ROWNUM

结果会是。

+----+-----------+-------+
| id |   name    | score |
+----+-----------+-------+
|  7 | ASomeName |   80  |
|  6 | Bsomename |   150 |
+----+-----------+-------+

无论有多少条记录,DB都会执行上述步骤,因此当您有订单并且有许多行满足条件时,Query将非常慢。

我不明白ROWNUM是在检索记录之前还是之后应用。我希望“之前”是有效的,而“之后”则不适用于大型结果集。

ROWNUMS是给定给满足所有给定条件的行的索引。DB将继续检查每行应用WHERE子句中提供的所有条件,如果everythig都很好,则为该行分配一个数字,然后转到下一行。正如文档所说,这意味着所有条件都得到满足。ROWNUM is evaluated AFTER records are selected from the database

在执行 ORDER BY 条款之前。

ROWNUM与其他数据库(MySQL,Postgrage等)中的LIMIT不同。即 LIMIT 查找所有行,对它们进行排序,然后返回有限的结果。而 ROWNUM 将在满足所有条件后立即分配给行。这就是休眠生成的内部查询以获得一致的排序结果的原因。

如果使用上表中给出的相同数据,则执行以下查询。

select * from user where score <= 500 where row_num < 3 order by name;

您将获得以下结果。

+----+-----------+-------+
| id |   name    | score |
+----+-----------+-------+
|  3 | Name2     |   300 |
|  2 | Name3     |   200 |
+----+-----------+-------+

这是因为 DB 开始查找满足条件的行(得分 <= 500),为每个行提供 ROWNUM 索引,直到 ROWNUM < 3,然后按名称对行进行排序。Oracle 将在基于查询的其余部分将行标识为结果集的一部分后立即应用 rownum 谓词

阅读这篇文章和这篇文章,他们真的很详细。


答案 2

推荐