添加 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 谓词
阅读这篇文章和这篇文章,他们真的很详细。