当前位置: 首页 > 面试题库 >

使用HQL进行休眠分页

方坚壁
2023-03-14
问题内容

细节

来自应用程序的HQL查询:

Query q = session.createQuery("from RequestDao r order by r.id desc");
            q.setFirstResult(0);
            q.setMaxResults(50);

查询返回300万条记录,而对于分页,我们仅设置了其中的50条记录,分页页面的运行速度非常慢,因为每次刷新时,我们都调用查询来获取300万条记录,而其中只有50条记录。

我的主要问题是

HQL是始终运行并命中数据库还是运行命中会话或内存以查找数据,如果它每次都运行时命中数据库并获取结果集,那么从性能的角度来看,这是非常合适的,什么是改进的最佳解决方案它?

在hibernate状态下使用HQL是一种方法,我们可以查询数据库并首先仅获取50条记录,然后根据用户要求获取其他记录。这个挑战确实使应用程序陷入瘫痪,那么解决此问题的最佳方法是什么?

日志中生成的HQL查询

from com.delta.dao.RequestDao r order by r.id desc

hibernate生成的查询

select
    getrequest0_.ID as ID24_,
    getrequest0_.TIME as START3_24_,
    getrequest0_.STAT as STATUS24_,
    getrequest0_.SUM as SUMMARY24_,
    getrequest0_.OUTNAME as OUTPUT7_24_,
    getrequest0_.INPNAME as INPUT8_24_,
    getrequest0_.REQUEST_DATE as requestT9_24_,
    getrequest0_.PARENT_ID as PARENT10_24_,
    getrequest0_.INTER_TYPE as INTERPO60_24_,
    getrequest0_.OPEN_INT as OPEN61_24_,
    getrequest0_.SOURCE_TYPE as SOURCE62_24_,
    getrequest0_.TARGET_TYPE as TARGET20_24_,
    getrequest0_.SOURCE as SOURCE14_24_,
    getrequest0_.COPY_DATA as COPY16_24_,
    getrequest0_.CURVE as GENERATE63_24_,
    getrequest0_.TITLE as TITLE24_,
    getrequest0_.TIME_ID as TIMESERIES12_24_,
    getrequest0_.TASK_NAME as TASK51_24_ 
from
    REQUEST getrequest0_ 
where
    getrequest0_.KIND='csv' 
order by
    getrequest0_.ID desc

这是查询的 解释计划

| id | select_type | 桌子| 类型 可能的钥匙| 关键 key_len | 参考| 行| 过滤 额外|
 | 1 | 简单 getrequest0_ | 参考| TR_KIND_ID | TR_KIND_ID | 6 | const | 1703018 | 100.00 | 在哪里使用

附加信息:在50条记录的限制下使用和​​不使用order by子句的查询运行时间

如果我运行query with order子句,则查询花费 0.0012s 的设置LIMIT 50without order子句,相同的查询花费 0.0032s的sameLIMIT 50

另外,我们如何查找是否:

  1. 特定的HQL查询正在命中数据库,而不是缓存或从会话中获取信息?
  2. 是真的,HQL查询将始终运行并命中数据库以获取结果,而Criteria将运行并命中会话或缓存并从中获取结果吗?
  3. 同样在我下面提到的查询中:
    a) Query q = session.createQuery("from RequestDao r order by r.id desc");
    

    b) q.setFirstResult(0);
    c) q.setMaxResults(50);

在a处,是从数据库获取结果并将其存储在内存中,还是在不存在的地方,这时结果集中有300万个结果,然后在b和c处设置偏移值和限制,因此在页面上只看到50个结果,所以现在剩下300万条记录,在第二次调用此查询时,我们再次访问数据库并获得300万条记录并将其存储在内存中,然后在c处再次设置50条记录并继续执行上。

这个问题对我来说尚不明确,因此,如果有人可以提供清晰详细的解释,说明它的工作方式以及解决该问题的最佳方法,将不胜感激。

更新资料

事实证明,问题与页面上的记录显示无关,但是我在该页面上进行了过滤,并且在每个请求上都再次从数据库中获取所有下拉值,并且其中存在一些时髦的事情导致页面加载时间增加。

我正在对数据库进行多个嵌套的hibernate查询,并返回结果,什么是解决此问题的最佳解决方案?


问题答案:

您的查询告诉数据库对满足WHERE子句的所有记录进行排序。在返回前50名之前,它可能会排序数百万条记录。

编辑1/26:现在已经弄清了具体问题,我将尝试更具体地回答。

  1. 每次执行这样的查询时,Hibernate都会进入数据库。甚至还会将会话中的所有新/更新数据刷新到磁盘。如果这是您的情况,则此行为可能会导致速度变慢。

  2. 在大多数情况下,使用Hibernate Query API的效果通常都很好,并且与各种数据库平台兼容。如果您真的很想降低数据访问层的性能,可以编写自己的本机SQL查询来选择前50个结果。但是,一旦这样做,您几乎肯定会失去数据库独立性。因此,请评估您的成本与收益。

您的查询运行时间似乎在毫秒级范围内。这通常与将数据存储在磁盘上的关系数据库一样好。因此,您可能需要评估您是否确实存在性能问题。

编辑1/27:好的。看起来好像页面的总体设计中存在问题。我使用AJAX已有大约7年了,因此在浏览表格的页面时,我通常不必等待筛选UI控件重绘。我想,切换应用程序UI框架不是您的选择。您必须找出如何优化下拉列表等数据的加载。此数据是否经常更改?您可以将其缓存在应用程序中的某个位置吗?如果您必须每次都加载它们,是否可以只获取显示字符串而不是整个对象而摆脱困境?



 类似资料:
  • 问题内容: 我对HQL查询和hibernate有疑问。 我有一个用户类和一个角色类。用户可以具有许多角色。所以我有一个像这样的ManyToMany关系: 在用户类别中: 在角色类中: 此映射创建了存储关系的第三个表(PORTAIL_USERROLE)。像这样一切正常。当我有一个用户时,我将检索角色。 但是,我的问题是:在HQL查询中,如何获得具有特定角色的所有用户?任何类都代表PORTAIL_US

  • 问题内容: 如何在Hibernate中编写此SQL查询?我想使用Hibernate创建查询,而不是创建数据库。 我在SQLServer2008中创建了实体类, 我试图以多种方式构建有效的选择查询,但仍然无法正常工作。 实体有问题吗? 问题答案: 仅当实体之间存在关联时才能使用联接。您的Employee实体不应将名称为,类型为的字段映射到列。它应该与Team实体具有ManyToOne关联,并映射为J

  • 问题内容: 如何在Hibernate中编写此SQL查询?我想使用Hibernate创建查询,而不是创建数据库。 我在SQLServer2008中创建了实体类, 我试图以多种方式构建有效的选择查询,但仍然无法正常工作。 实体有问题吗? 问题答案: 连接只能在实体之间存在关联时使用。您的Employee实体不应将名称为,类型为的字段映射到列。它应该与Team实体具有ManyToOne关联,并映射为Jo

  • 问题内容: 我有两个实体:和。我正在使用Hibernate 3.6。 如何使用hibernate标准实现这一目标,最重要的是,我必须将其用于分页。 而“我的道”如下所示以显示jqgrid中的“问题”列表 公共列表showHelpDeskIssues(DetachedCriteria dc,int from,int size){ 问题答案: 您可以尝试以下 这里parent是中的属性名称,child

  • 问题内容: 我有两个表,并且在数据库中。在表中,我有一个Integer 对该表的引用。(idA是B的外键)当我使用hibernate- tools进行反向工程时,会生成两个Java对象。 和 但是我想要 我怎样才能做到这一点? 谢谢, 问题答案: 因此,我找到了一个解决方案:创建一个自定义并将方法的返回更改为。

  • 问题内容: 我想“试运行” Hibernate HQL查询。那就是我想知道Hibernate将从给定的HQL查询中执行哪些实际的SQL查询,而无需实际针对实际数据库执行HQL查询。 我可以访问表的hibernate映射,HQL查询字符串,数据库的方言。如果需要,我也可以访问数据库。 现在,如何找到Hibernate可以从HQL生成的所有SQL查询,而无需实际对任何数据库执行查询?有什么工具吗? 请