1. 程式人生 > >WARNING: firstResult/maxResults specified with collection fetch; applying in memory!

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

lis else 並且 object use nat 警告 || 出現

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!