了解Hibernate的标准#setMaxResults

Kev*_*ith 8 java sql oracle hibernate

文件说:

Criteria setMaxResults(int maxResults)
>Set a limit upon the number of objects to be retrieved.
Run Code Online (Sandbox Code Playgroud)

假设我有以下内容Criteria:

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

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

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

但是,当我查看ROWNUM常见问题时,我不明白是否ROWNUM检索记录之前或之后应用.我希望"之前"是有效的,而"之后"则不适用于大的结果集.

在从数据库中选择记录并在执行ORDER BY子句之前评估ROWNUM.

bit*_*kot 14

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

是的,它只返回一行,hibernate使用db特定功能来限制结果.Hibernate将不会拾取100万行,但db会选择第一行(此语句与hibernate生成的查询有关ROWNUM).

假设你有一个名为的表user,其中你有8行.

+----+-----------+-------+
| 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 |
+----+-----------+-------+
Run Code Online (Sandbox Code Playgroud)

现在,您运行以下条件.

criteria.add(Restriction.le("score", 500));
criteria.addOrder(Order.asc("name"));
criteria.setMaxResults(2);
Run Code Online (Sandbox Code Playgroud)

以下是Hibernate生成的查询.

select * from(select * from user where score <= 500 order by name) where ROWNUM < 3; 
Run Code Online (Sandbox Code Playgroud)

DB将按以下顺序执行它.

  • 找到得分小于或等于500的所有行.这里将找到6行.
  • 按名称按升序排序所有行.
  • 分配ROWNUM给每一行.
  • 找到ROWNUM小于3的所有行并返回它们.

结果将是.

+----+-----------+-------+
| id |   name    | score |
+----+-----------+-------+
|  7 | ASomeName |   80  |
|  6 | Bsomename |   150 |
+----+-----------+-------+
Run Code Online (Sandbox Code Playgroud)

无论有多少记录,DB都会执行上述步骤,所以当你有顺序并且有很多行满足条件时,查询会非常慢.

我不明白在检索记录之前或之后是否会应用ROWNUM.我希望"之前"是有效的,而"之后"则不适用于大的结果集.

ROWNUMS是给予满足所有给定条件的行的索引.DB将继续检查每一行是否应用WHERE子句中提供的所有条件,如果everythig没有问题,则为该行分配一个数字,然后转到下一行.正如医生所说,ROWNUM is evaluated AFTER records are selected from the database意味着满足所有条件.

在执行ORDER BY子句之前.

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

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

select * from user where score <= 500 where row_num < 3 order by name;
Run Code Online (Sandbox Code Playgroud)

您将获得以下结果.

+----+-----------+-------+
| id |   name    | score |
+----+-----------+-------+
|  3 | Name2     |   300 |
|  2 | Name3     |   200 |
+----+-----------+-------+
Run Code Online (Sandbox Code Playgroud)

这是因为DB开始查找满足条件的行(得分<= 500),给它们每个ROWNUM索引直到ROWNUM <3,然后按名称排序行.一旦根据查询的其余部分将行标识为结果集的一部分,Oracle将应用rownum谓词

阅读本文这些文章,他们非常详细.