【问题标题】:How to limit result set with joined collection如何使用加入集合限制结果集
【发布时间】:2019-01-24 10:55:52
【问题描述】:

我有一个用例,用户可以输入文本,系统会搜索匹配的发票。输入的文本可以匹配 Invoice 和 Invoice Lines 上的多个字段。

用户只能根据角色访问所有发票的子集。但这可能是一份包含数千张发票的清单。

搜索是通过与通配符相结合的直接类似搜索来完成的。 (查询是用hql写的)

在显示结果时,我们希望将其限制为 50,以不根据用户搜索的内容选择/处理数千个条目。但是,通过我加入的方式,数据库无法强制执行此限制。

我们曾经有过类似(伪代码)的东西

select * from tbl_invoice
join tbl_useraccess .... :userid //a few joins happen here to limit to invoices             
//where the user has access to
where number like :input
or name like :input
or id in (select id from InvoiceLine where reference like :input)
limit top 50

这具有非常糟糕的性能,因为搜索是在每个发票行上完成的,而不仅仅是您可以访问的那些,但总是给出正确的 50 行。

我把它改成了

select * from tbl_invoice invoice
join tbl_useraccess .... :userid 
join tbl_invoiceline line on invoice.id = line.invoice_id    
where number like :input
or name like :input
or line.reference like :input
limit top 50

性能要好得多(之前的语句会超时),但限制不起作用,因为一张发票可能有多行。

我们可以从数据库中检索所有结果,将其映射到 java 对象并在 Java 中执行最多 50 个结果,但我担心如果用户检索数以百万计的记录,这可能会炸毁我们的内存。

因此,总而言之,我正在寻找一种更好的方法来检索固定的结果列表,同时也能够在链接的 1-n 实体中进行搜索

【问题讨论】:

  • 也许你可以通过使用 sub-select 来克服这个问题,但我不完全确定在 hql 中是如何完成的,也许看看这个问题,它提供了一些附加链接:stackoverflow.com/questions/8784354/…
  • 您好 Lino,感谢您的反馈。我们确实使用休眠 setMaxResults() 来限制输出。使用子查询是不可能/困难的(?),因为我们第一次尝试使用子查询但查询所有行而不是用户可以访问的行。用户访问权限在发票级别进行管理。

标签: java hibernate spring-boot jpa query-optimization


【解决方案1】:
select * from InvoiceLine line where reference like :input
join tbl_invoice invoice on invoice.id = line.invoice_id  
join tbl_useraccess .... :userid 
where number like :input
or name like :input
or line.reference like :input
limit top 50

这会将您的发票行数限制为 50。

【讨论】:

  • 嗨娜雅,感谢您的反馈。我的目标是显示 50 张发票,其中每张发票可以有 1 到 5000 行。限制发票行,可能只显示一张发票
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多