试图搜索一个返回很多结果的关键词时,系统报内存溢出的异常:
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全部取出来,
非常的占内存,而且非常慢。现在只显示第一页的内容,就快多了。