Hibernate Search 之 搜寻结果分页

Hibernate Search 之 搜索结果分页

试图搜索一个返回很多结果的关键词时,系统报内存溢出的异常:

 

java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOf(Arrays.java:2882)
	at java.lang.StringCoding.safeTrim(StringCoding.java:75)
	at java.lang.StringCoding.access$100(StringCoding.java:34)
	at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:151)
	at java.lang.StringCoding.decode(StringCoding.java:173)
	at java.lang.String.<init>(String.java:443)
	at org.apache.lucene.store.IndexInput.readString(IndexInput.java:127)
	at org.apache.lucene.index.FieldsReader.addField(FieldsReader.java:392)
	at org.apache.lucene.index.FieldsReader.doc(FieldsReader.java:229)
	at org.apache.lucene.index.SegmentReader.document(SegmentReader.java:948)
	at org.apache.lucene.index.DirectoryReader.document(DirectoryReader.java:506)
	at org.apache.lucene.index.MultiReader.document(MultiReader.java:241)
	at org.apache.lucene.index.IndexReader.document(IndexReader.java:947)
	at org.apache.lucene.search.IndexSearcher.doc(IndexSearcher.java:152)
	at org.hibernate.search.query.QueryHits.doc(QueryHits.java:73)
	at org.hibernate.search.engine.DocumentExtractor.extract(DocumentExtractor.java:107)
	at org.hibernate.search.query.FullTextQueryImpl.list(FullTextQueryImpl.java:331)
	at org.simon.pim8.server.search.SearchDataSource.execute(SearchDataSource.java:49)

 

用google搜索了一下,没什么头绪。因为-Xmx1024M早就设置了,而搜索其他的关键词又不会出错。

仔细想了一下,只有可能是因为一次搜索出来的结果太多,导致lucene使用的内存溢出了。

于是,考虑将搜索结果分页。

 

其实hibernate search的分页也很简单,甚至比hibernate的分页还简单。因为hibernate的分页,还要

先去 project 一个 count,获取总数才能分页,而hibernate search本身,已经可以通过 fullTextQuery的

getResultSize来获取总数了。接下来,就是从 request 里面获取 first result 和每个page的结果数量,

然后用

fullTextQuery.setMaxResults((int)req.getBatchSize());
fullTextQuery.setFirstResult((int)req.getStartRow());

 就可以了,这样 fullTextQuery.list 出来的结果,就已经是分页的了。至于得到结果之后如何展示,

那就更加容易了。对于 SmartGWT 来说,只要设置

        res.setStartRow( req.getStartRow());
        res.setEndRow( req.getStartRow() + results.size());
        res.setTotalRows( fullTextQuery.getResultSize());
        res.setStatus(DSResponse.STATUS_SUCCESS);
        res.setData(results);

 就 ok 了,SmartGWT的 ListGrid会自动做分页,而且是滚动条形式的分页。

使用分页之后,不仅不会出现溢出问题,而且原来结果集比较多,搜索比较慢的

情况,也都没有了。因为不分页的话,会把所有结果的document全部取出来,

非常的占内存,而且非常慢。现在只显示第一页的内容,就快多了。