WARNING: firstResult/maxResults specified with collection fetch; applying in memory!

Posted 风来了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WARNING: firstResult/maxResults specified with collection fetch; applying in memory!相关的知识,希望对你有一定的参考价值。

QueryTranslatorImpl

@Override
    public List list(SessionImplementor session, QueryParameters queryParameters)
            throws HibernateException {
        // Delegate to the QueryLoader...
        errorIfDML();

        final QueryNode query = (QueryNode) sqlAst;
        final boolean hasLimit = queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
        final boolean needsDistincting = ( query.getSelectClause().isDistinct() || hasLimit ) && containsCollectionFetches();

        QueryParameters queryParametersToUse;
        if ( hasLimit && containsCollectionFetches() ) {
            LOG.firstOrMaxResultsSpecifiedWithCollectionFetch();
            RowSelection selection = new RowSelection();
            selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() );
            selection.setTimeout( queryParameters.getRowSelection().getTimeout() );
            queryParametersToUse = queryParameters.createCopyUsing( selection );
        }
        else {
            queryParametersToUse = queryParameters;
        }

        List results = queryLoader.list( session, queryParametersToUse );

        if ( needsDistincting ) {
            int includedCount = -1;
            // NOTE : firstRow is zero-based
            int first = !hasLimit || queryParameters.getRowSelection().getFirstRow() == null
                        ? 0
                        : queryParameters.getRowSelection().getFirstRow();
            int max = !hasLimit || queryParameters.getRowSelection().getMaxRows() == null
                        ? -1
                        : queryParameters.getRowSelection().getMaxRows();
            List tmp = new ArrayList();
            IdentitySet distinction = new IdentitySet();
            for ( final Object result : results ) {
                if ( !distinction.add( result ) ) {
                    continue;
                }
                includedCount++;
                if ( includedCount < first ) {
                    continue;
                }
                tmp.add( result );
                // NOTE : ( max - 1 ) because first is zero-based while max is not...
                if ( max >= 0 && ( includedCount - first ) >= ( max - 1 ) ) {
                    break;
                }
            }
            results = tmp;
        }

        return results;
    }

 

hasLimit && containsCollectionFetches()

这句判断,如果满足了这个条件,RowSelection将会被重新生成,原本分页需要的firstRow和maxRows属性将会丢失,后面的数据库分页自然也无法进行。
Hibernate这么做的原因从代码上也很容易理解,如果查询需要限制条数(limit/offset)并且需要fetch结合对 象,则重新生成RowSelection。

进一步解释,就是当一个实体(A)和另一个实体(B)是One-To-Many关系的时候,一个需要fetch 的典型查询语句是
“select distinct a from A a left join fetch a.b”
由于1个A可能对应多个B,这个时候数据库查询的结果条数和需要生成的A对象的条数可能不一致,
所以无法利用数据库层的分页来实现,因为你真正想分页的是A而不是A left join B。

出现这个警告就是提醒你这个查询实际上是查询了所有满足条件的数据,Hibernate是在内存中对其进行了假分页的处理。











以上是关于WARNING: firstResult/maxResults specified with collection fetch; applying in memory!的主要内容,如果未能解决你的问题,请参考以下文章

QMessageBox:warning里怎么显示中文

什么电影以fbi warning开头

第三方库Tensorflow编写程序正常运行,出现warning的问题

ffmpeg的迷惑警告 [warning]stream 0, timescale not set,ffmpeg日志等级的设置

转码:gcc在代码中禁止某些warning

Python忽略warning警告错误