Hibernate 休眠:执行非常复杂的选择/筛选。分页是一个好的选择吗?

Hibernate 休眠:执行非常复杂的选择/筛选。分页是一个好的选择吗?,hibernate,pagination,Hibernate,Pagination,我必须找到数据库中的项目。首先,我使用一个数据库查询,然后是一个过滤器。此筛选器太复杂,无法重写为数据库查询,它会从列表中删除与筛选器不匹配的项 我们将Hibernate用于大型数据库 那么,我如何在不对生产性能产生太大影响的情况下处理两步流程呢 我的想法是使用Hibernate分页。因此,从数据库中检索100个对象,应用过滤器,直到达到阈值(比如200)。然后返回结果进行进一步处理 使用Hibernate分页:如何检索一系列(如30)项的页面?假设(实际上)不可能将筛选器转换为数据库查询 高级

我必须找到数据库中的项目。首先,我使用一个数据库查询,然后是一个过滤器。此筛选器太复杂,无法重写为数据库查询,它会从列表中删除与筛选器不匹配的项

我们将Hibernate用于大型数据库

那么,我如何在不对生产性能产生太大影响的情况下处理两步流程呢

我的想法是使用Hibernate分页。因此,从数据库中检索100个对象,应用过滤器,直到达到阈值(比如200)。然后返回结果进行进一步处理

使用Hibernate分页:如何检索一系列(如30)项的页面?假设(实际上)不可能将筛选器转换为数据库查询

高级别方法是:

WHILE not enough items found DO
  find the next page/series of items
  apply a filter on the found items to remove invalid ones
  IF enough items found STOP
DONE
对于查找下一页/批次/系列项目,我看到了很多答案,如:

public List<T> getItems( Session session, int pageSize, int currentPage) {
    Criteria criteria = session.createCriteria(Item.class);
    criteria.setFirstResult( calculateOffset( currentPage); 
    criteria.setMaxResults( pageSize);
    return criteria.list();
}
private int calculateOffset(int currentPage, int pageSize) {
    return ((pageSize * currentPage) - pageSize);
}
public List getItems(会话会话、int pageSize、int currentPage){
条件=session.createCriteria(Item.class);
标准。setFirstResult(计算偏移量(当前页);
标准.setMaxResults(页面大小);
返回条件。list();
}
私有int-calculateOffset(int-currentPage,int-pageSize){
返回((页面大小*当前页面)-页面大小);
}
是的,无法将“筛选器”转换为数据库搜索标准。从数据库请求所有对象对(其他)生产用户的数据库性能有太大影响

下面是我到目前为止如何实现的一个示例,它太慢了。 是否有更快更好的方法滚动/分页数据库

// The production database should not be queried too heavily
List<Item> endresult = new ArrayList<Item>();
// Building a complex db query
Criteria searchCriteria = buildFindAanleveringForCriteria( criteria); 
int startSearchingAt = 0;
int searchLimit = criteria.getMaxResults();
int currentPage = 0;
searchCriteria.setFirstResult( startSearchingAt);
searchCriteria.setMaxResults( searchLimit);
while( ! searchLimitIsReached) {
    List<Item> queryResult = searchCriteria.list();
    if( queryResult == null || queryResult.isEmpty()) {
        searchLimitIsReached = true; // no more data available
    }
    // all kinds of processing goes here
    // applying a very complex filter on the list to remove invalid items
    //   the filter cannot be used in a query to the database
    endresult.addAll( filterOnStatus( queryResult, criteria.getStatus()));
    // Stop if no filtering was done on the aanleverstatus. Wachten status are only near THIS (now) moment
if ( aanleveringen.size() >= criteria.getMaxResults()) {
        searchLimitIsReached = true; // no further search is needed.
    }
    // Where to start the next page of results
    startSearchingAt = (++currentPage * searchLimit);
    searchCriteria.setFirstResult( startSearchingAt);
}
//不应过度查询生产数据库
List endresult=new ArrayList();
//构建复杂的数据库查询
Criteria searchCriteria=BuildFindAnleveringForCriteria(Criteria);
int startSearchingAt=0;
int searchLimit=criteria.getMaxResults();
int currentPage=0;
searchCriteria.setFirstResult(StartSearchAgent);
searchCriteria.setMaxResults(searchLimit);
而(!searchLimitIsReached){
List queryResult=searchCriteria.List();
if(queryResult==null | | queryResult.isEmpty()){
searchLimitIsReached=true;//没有更多可用数据
}
//这里有各种各样的加工
//在列表上应用非常复杂的筛选器以删除无效项
//无法在对数据库的查询中使用筛选器
addAll(filternostatus(queryResult,criteria.getStatus());
//如果未对aanleverstatus进行过滤,则停止。Wachten状态仅在此时(现在)附近
if(aanleveringen.size()>=criteria.getMaxResults()){
searchLimitIsReached=true;//不需要进一步搜索。
}
//从哪里开始下一页的结果
startSearchingAt=(++currentPage*搜索限制);
searchCriteria.setFirstResult(StartSearchAgent);
}

那么,我们怎样才能找到一个具有(非常)复杂的选择/过滤逻辑且性能足够好的解决方案呢

选项1:Spring/hibernate分页-请参阅上面的解决方案。搜索屏幕的建立大约需要400秒

选项2:休眠/可滚动结果。如下所示:

String hql=“FROM Foo f order by f.name”;
Query=session.createQuery(hql);
int pageSize=10;
ScrollableResultsScroll=query.scroll(仅限ScrollMode.FORWARD_);
resultsScroll.first();
结果滚动滚动(0);
List fooPage=Lists.newArrayList();
int i=0;
而(页面大小>i++){
添加((Foo)resultScroll.get(0));
如果(!resultScroll.next())
打破
}
构建结果花费了400多秒

解决方案3:我们构建了一个存储过程,因此将逻辑放在数据库中。许多架构师希望将逻辑集中在一个位置,大多数情况下不在数据库中。我们构建此选项只是为了看看此解决方案的性能是否会更好。 通过描述了从hibernate调用存储过程的解决方案,大约需要10秒才能完成。 因此,我们将这个特定查询和过滤器的所有逻辑放在数据库中的一个位置


选项4:Java中嵌入的SQL语句?这将是一个太复杂的逻辑,无法放入SQL查询中。

这太抽象,无法进行评论,因为Hibernate和JPA都支持筛选和分页,这两个版本都在问题上进行了标记。也许一个具体的案例将有助于提供输入。此外,问题也被标记使用
spring data jpa
但仅指本机Hibernate代码。解决方案是使用Hibernate还是使用spring data jpa?@manish-我必须使用问题中给出的代码。我删除了jpa。如果没有看到过滤对象的代码,就无法确定是否有更好的方法。
String hql = "FROM Foo f order by f.name";
Query query = session.createQuery(hql);
int pageSize = 10;     
ScrollableResults resultScroll = query.scroll(ScrollMode.FORWARD_ONLY);
resultScroll.first();
resultScroll.scroll(0);
List<Foo> fooPage = Lists.newArrayList();
int i = 0;
while (pageSize > i++) {
    fooPage.add((Foo) resultScroll.get(0));
    if (!resultScroll.next())
        break;
}