hibernate search 我就很少說了,它是基於lucene的全文檢索工具,記得上大學那時候接觸了compass全文檢索工具,後來也沒怎麼用,再後來這傢伙不更新了,因此hibernate就推出了本身的基於lucene的全文檢索工具就是這傢伙hibernate Search。 java
不用說自然的優點就是能夠無縫的和hibernate集成甚至不須要什麼配置,一直在更新中,最近想在本身的博客裏面加入搜索功能,本想用比較熱乎的solr,找了半天資料仍是放棄了,用在個人博客裏面有點大題小作了,因此天然就鎖定了hibernate search,簡單嘛,並且不須要什麼配置對hibernate jpa都頗有好,雖然我用的是spring data jpa 可是我想也不會影響它的使用。 linux
廢話就不說了,咱們進入正題,從配置開始: spring
1.persistence.xml 文件裏面加入: apache
<property name="hibernate.search.default.directory_provider" value="filesystem"/>
<property name="hibernate.search.default.indexBase" value="e:/index"/>
若是是linux系統就把路徑換一下,配置搞定,是否是很簡單,其餘地方不須要任何改動。 api
2.實體: app
這不用解釋了吧,你想要在那個實體上面作檢索就配置那個實體,說白了就是加一些註解。 maven
我就簡略的寫了,至於註解的含義你們在網上找找。 ide
@Indexed
@Analyzer(impl=SmartChineseAnalyzer.class)
public class Posts implements java.io.Serializable { 工具
@Id //這裏不須要加什麼,若是你用的是hibernate作持久層須要加@DocumentId 這個註解
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
} post
@Column(name = "post_title", nullable = false,length=1000)
@Field
@Boost(2)
public String getPtitle() {
return ptitle;
}
public void setPtitle(String ptitle) {
this.ptitle = ptitle;
}
@Lob
@Field
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
還須要我解釋麼,我以爲不須要了。
就這麼簡單,加幾個註解就能夠了,系統在運行時會自動生成索引文件
3.檢索服務:
這個主要是放在service層,由於我用的是spring data jpa
@Service("postService")
public class PostServiceImpl implements PostService{
@Autowired
private EntityManagerFactory emf;
這裏我在這個實現類裏面注入了在applicationContext.xml 裏面配置的EntityManagerFactory, 我想你應該懂這些
public QueryResult<Posts> search(int nowpage,int size,String keyWord) { QueryResult<Posts> queryResult = new QueryResult<Posts>(); EntityManager em = emf.createEntityManager(); FullTextEntityManager fManager = Search.getFullTextEntityManager(em); QueryBuilder qb = fManager.getSearchFactory().buildQueryBuilder().forEntity(Posts.class).get(); Query q = qb.keyword().onFields("ptitle","description","content").matching(keyWord).createQuery(); FullTextQuery fq = fManager.createFullTextQuery(q, Posts.class); queryResult.setTotalRecord(fq.getResultSize()); List<Posts> re = fq.setFirstResult(nowpage).setMaxResults(size).getResultList(); re = hightLight(q, re, Posts.class, null, "ptitle","description","content"); queryResult.setResultList(re); return queryResult; }
/** * @param org.apache.lucene.search.Query luceneQuery * @param searchResults 搜索結果集 * @param searchResultClass 搜索結果類型 * @param excludeFields 要排除高亮的字段 * @param fieldNames 須要高亮的字段 * @return 高亮後的searchResults */ private <E> List<E> hightLight(Query luceneQuery, List<E> searchResults, Class<E> searchResultClass, List<String> excludeFields, String... fieldNames) { SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<b><font color=\"red\">", "</font></b>"); QueryScorer queryScorer = new QueryScorer(luceneQuery); Highlighter highlighter = new Highlighter(formatter, queryScorer); Analyzer analyzer = new SmartChineseAnalyzer(); for (E e : searchResults) { for (String fieldName : fieldNames) { if(null != excludeFields && excludeFields.contains(fieldName)){ continue; } Object fieldValue = ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(searchResultClass, fieldName).getReadMethod(), e); String hightLightFieldValue = null; if(fieldValue instanceof String){ try { hightLightFieldValue = highlighter.getBestFragment( analyzer, fieldName , String.valueOf(fieldValue)); } catch (Exception e1) { e1.printStackTrace(); } ReflectionUtils.invokeMethod(BeanUtils.getPropertyDescriptor(searchResultClass, fieldName).getWriteMethod(), e, hightLightFieldValue); } } } return searchResults; }
這裏面加入了分頁效果,高亮效果,這段代碼我也是在網上找的修改了一下,若是誰還有更好的能夠留言分享一下。
package com.weirblog.fenye; import java.util.List; /** * 查詢結果集,包括數據和總數 * @author db2admin * * @param <T> */ public class QueryResult<T> { /** 查詢得出的數據List **/ private List<T> resultList; /** 查詢得出的總數 **/ private int totalRecord; public List<T> getResultList() { return resultList; } public void setResultList(List<T> resultList) { this.resultList = resultList; } public int getTotalRecord() { return totalRecord; } public void setTotalRecord(int totalRecord) { this.totalRecord = totalRecord; } }
package com.weirblog.fenye; import java.util.List; /** * 分頁數據包裝,包括分頁信息和List數據 */ public class PageView<T> { /** 分頁數據 **/ private List<T> records; /** 頁碼開始索引和結束索引 **/ private PageIndex pageIndex; /** 總頁數 **/ private int totalPage = 1; /** 每頁顯示記錄數 **/ private int maxResult = 10; /** 當前頁 **/ private int currentPage = 1; /** 總記錄數 **/ private int totalRecord; /** 每次顯示多少頁,必須保證大於3頁,保證左右連接均可以使用 **/ private int viewPageCount = 10; /** 要獲取記錄的開始索引 **/ public int getFirstResult() { return (this.currentPage - 1); // return (this.currentPage - 1) * this.maxResult; } public int getViewPageCount() { return viewPageCount; } public void setViewPageCount(int viewPageCount) { this.viewPageCount = viewPageCount; } public PageView(int maxResult, int currentPage) { this.maxResult = maxResult; this.currentPage = (currentPage <= 0 ? 1 : currentPage); } public PageView(int currentPage) { this.currentPage = (currentPage <= 0 ? 1 : currentPage); } public void setQueryResult(QueryResult<T> qr) { setTotalRecord(qr.getTotalRecord()); setRecords(qr.getResultList()); } public int getTotalRecord() { return totalRecord; } public void setTotalRecord(int totalRecord) { this.totalRecord = totalRecord; setTotalPage(this.totalRecord % this.maxResult == 0 ? this.totalRecord / this.maxResult : this.totalRecord / this.maxResult + 1); } public List<T> getRecords() { return records; } public void setRecords(List<T> records) { this.records = records; } public PageIndex getPageIndex() { return pageIndex; } public int getTotalPage() { return totalPage; } public void setTotalPage(int totalPage) { this.totalPage = totalPage; this.pageIndex = PageIndex.getPageIndex(viewPageCount, currentPage, totalPage); } public int getMaxResult() { return maxResult; } public int getCurrentPage() { return currentPage; } }這些關於分頁的封裝我就不解釋了。
4.controller層:
@RequestMapping("/search") public String search(Integer page,String keyWord,Model model) { PageView<Posts> pageView = new PageView<Posts>(2, page!=null ? page:1); pageView.setQueryResult(postService.search(pageView.getFirstResult(), pageView.getMaxResult(), keyWord)); model.addAttribute("pageView", pageView); return "/search"; }這個也應該不須要解釋什麼。
還有一些就是jar包了我用的是最新穩定版本5.3.0
hibernate-search-engine-5.3.0.Final
hibernate-search-orm-5.3.0.Final
lucene-analyzers-common-4.10.4
lucene-core-4.10.4
xml-apis-1.3.03
E:\gj\hibernate-search-5.3.0.Final\dist\lib\required
重複的去掉
hibernate 須要也是最新的了4.3.10
lucene須要:
lucene 這些有的hibernate search包裏面沒有 本身去lucene官網上下載,還有一個辦法就是本身搭建一個maven工程加入:
<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-search-orm</artifactId> <version>5.3.0.Final</version> </dependency>就是這樣才搞定了jar包缺失的問題,很扯淡是否是。
最後仍是看看效果吧:
還行吧。