如何限制联接集合的结果集

时间:2019-01-24 10:55:52

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

我有一个用例,用户可以输入文本,然后系统搜索匹配的发票。键入的文本可以在“发票”和“发票行”的多个字段上匹配。

根据角色,用户只能访问所有发票的一部分。但这可能是数千张发票的清单。

通过与通配符组合的直接搜索来完成搜索。 (查询用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实体中进行搜索

1 个答案:

答案 0 :(得分:0)

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。