解決HIbernate分頁問題獲取表總行數的小Bug

raorq發表於2020-04-06
今天上午回來設計了一點新聞釋出系統周邊的功能,並實現了對新聞進行重新索引的功能。
但同時在列出相關新聞的時候遇到了麻煩。就是原本執行好好的分頁查詢程式碼,居然有個小蟲子跑出來,
很是令人不爽。說來也慚愧,Hibernate也用了那麼長時間了。可對底層API卻很不屬性。
查了下網路,把自己的一知半解說出來。

bug起源。
看看程式碼:
return (PageSupport) getHibernateTemplate().execute(
                
new HibernateCallback() ...{
                    
public Object doInHibernate(Session session)
                            
throws HibernateException ...{
                        Criteria criteria 
= detachedCriteria
                                .getExecutableCriteria(session);
                     
                        
                        logger.debug(
"SQL: " + Projections.rowCount());
                        
                        
                         
                        
//執行查詢
                        int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();

                     
                     
                        
                        
                        List items 
= criteria.setFirstResult(startIndex)
                        .setMaxResults(pageSize).list();
                
                        PageSupport ps 
= new PageSupport(items, totalCount,
                                pageSize, startIndex);
                        
                        
return ps;
                    }

                }
true);

相信大家對上面的程式碼也很熟悉了,這個程式碼第一次執行的時候沒問題。
等你去拿第2頁的時候,就提示說出現NullPointer。 發現是((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult())為Null, 也就是根本就拿不到表總數。
為此我思考了好一陣子。
後來看了別人的程式碼才煥然大悟。
看第2個程式碼:
return (PageSupport) getHibernateTemplate().execute(
                
new HibernateCallback() ...{
                    
public Object doInHibernate(Session session)
                            
throws HibernateException ...{
                        Criteria criteria 
= detachedCriteria
                                .getExecutableCriteria(session);
                        
                        CriteriaImpl impl 
= (CriteriaImpl) criteria;

                        
//先把Projection和OrderBy條件取出來,清空兩者來執行Count操作
                        Projection projection = impl.getProjection();
                        
                        logger.debug(
"SQL: " + Projections.rowCount());
                        
                        
                         
                        
//執行查詢
                        int totalCount = ((Integer) criteria.setProjection(Projections.rowCount()).uniqueResult()).intValue();

                        
//將之前的Projection和OrderBy條件重新設回去
                        criteria.setProjection(projection);
                        
if (projection == null...{
                            criteria.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
                        }

                     
                        
                        
                        List items 
= criteria.setFirstResult(startIndex)
                        .setMaxResults(pageSize).list();
                
                        PageSupport ps 
= new PageSupport(items, totalCount,
                                pageSize, startIndex);
                        
                        
return ps;
                    }

                }
true);

相關文章