Hibernate Search

也许你的项目正在使用Spring+Hibernate,而你正好需要建立全文检索。Hibernate search可以无缝得整合Hibernate和Lucene,帮助你快速实现功能强大的全文检索。

     Hibernate Search通过整合Hibernate core和Lucene建立持久化对象的索引。功能强大而配置简单。下载请到官方网站

     Hibernate Search运行的环境如下:

      1、JDK或JRE 5.0以上
      2、Hibernate-Search以及相应的依赖包
      3、Hibernate Core 3.2.X
      4、Hibernate Annotations 3.3.X
     
      首先将下载到的JAR包添加到你的项目中。
     
      新建一个领域模型
       
     

Java代码 复制代码  收藏代码
  1.       public class Book {  
  2.     Integer bookId;  
  3.     String title;  
  4.     String author;  
  5.     String publishDate;  
  6.     String summarize;  
  7.     public Integer getBookId() {  
  8.         return bookId;  
  9.     }  
  10.     public void setBookId(Integer bookId) {  
  11.         this.bookId = bookId;  
  12.     }  
  13.     public String getTitle() {  
  14.         return title;  
  15.     }  
  16.     public void setTitle(String title) {  
  17.         this.title = title;  
  18.     }  
  19.     public String getAuthor() {  
  20.         return author;  
  21.     }  
  22.     public void setAuthor(String author) {  
  23.         this.author = author;  
  24.     }  
  25.     public String getPublishDate() {  
  26.         return publishDate;  
  27.     }  
  28.     public void setPublishDate(String publishDate) {  
  29.         this.publishDate = publishDate;  
  30.     }  
  31.     public String getSummarize() {  
  32.         return summarize;  
  33.     }  
  34.     public void setSummarize(String summarize) {  
  35.         this.summarize = summarize;  
  36.     }  
  37.       
  38. }  
  39.         
      public class Book {
	Integer bookId;
	String title;
	String author;
	String publishDate;
	String summarize;
	public Integer getBookId() {
		return bookId;
	}
	public void setBookId(Integer bookId) {
		this.bookId = bookId;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getPublishDate() {
		return publishDate;
	}
	public void setPublishDate(String publishDate) {
		this.publishDate = publishDate;
	}
	public String getSummarize() {
		return summarize;
	}
	public void setSummarize(String summarize) {
		this.summarize = summarize;
	}
	
}
      


     
      接下来在类中加入Hibernate search注解
     

Java代码 复制代码  收藏代码
  1.      //索引名称  
  2.      @Indexed(index = "books")  
  3.      //分词器  
  4.      @Analyzer(impl = MMSegAnalyzer.class)  
  5.      public class Book {  
  6. Integer bookId;  
  7. String title;  
  8. String author;  
  9. String publishDate;  
  10. String summarize;  
  11.          
  12.       //以对象的唯一标志做为索引中文档的唯一标志  
  13.        @DocumentId  
  14. public Integer getBookId() {  
  15.     return bookId;  
  16. }  
  17. public void setBookId(Integer bookId) {  
  18.     this.bookId = bookId;  
  19. }  
  20.        //索引title字段,并设置了权重  
  21.        @Field(name = "title", index = Index.TOKENIZED, store = Store.YES, boost=@Boost(2f))  
  22. @Boost(1.5f)  
  23. public String getTitle() {  
  24.     return title;  
  25. }  
  26. public void setTitle(String title) {  
  27.     this.title = title;  
  28. }  
  29. public String getAuthor() {  
  30.     return author;  
  31. }  
  32. public void setAuthor(String author) {  
  33.     this.author = author;  
  34. }  
  35. public String getPublishDate() {  
  36.     return publishDate;  
  37. }  
  38. public void setPublishDate(String publishDate) {  
  39.     this.publishDate = publishDate;  
  40. }  
  41.         
  42.       //索引摘要字段,并设置权重  
  43.       @Field(name = "summarize", index = Index.TOKENIZED, store = Store.YES, boost=@Boost(1.2f))  
  44. public String getSummarize() {  
  45.     return summarize;  
  46. }  
  47. public void setSummarize(String summarize) {  
  48.     this.summarize = summarize;  
  49. }  
      //索引名称
      @Indexed(index = "books")
      //分词器
      @Analyzer(impl = MMSegAnalyzer.class)
      public class Book {
	Integer bookId;
	String title;
	String author;
	String publishDate;
	String summarize;
        
       //以对象的唯一标志做为索引中文档的唯一标志
        @DocumentId
	public Integer getBookId() {
		return bookId;
	}
	public void setBookId(Integer bookId) {
		this.bookId = bookId;
	}
        //索引title字段,并设置了权重
        @Field(name = "title", index = Index.TOKENIZED, store = Store.YES, boost=@Boost(2f))
	@Boost(1.5f)
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
	public String getPublishDate() {
		return publishDate;
	}
	public void setPublishDate(String publishDate) {
		this.publishDate = publishDate;
	}
       
       //索引摘要字段,并设置权重
       @Field(name = "summarize", index = Index.TOKENIZED, store = Store.YES, boost=@Boost(1.2f))
	public String getSummarize() {
		return summarize;
	}
	public void setSummarize(String summarize) {
		this.summarize = summarize;
	}
	
}
 



    本文没有使用注解来完成类和数据的映射,而是使用book.hbm.xml的映射文件,当然你不用对映射文件做任何改动。如果你想使用注解,直接在类里中加入注解即可。
   
     接下来需要修改hibernate.cfg.xml。在sessionFactory节中加入

Java代码 复制代码  收藏代码
  1. <property name="hibernate.search.default.directory_provider">  
  2.     org.hibernate.search.store.FSDirectoryProvider  
  3.      </property>  
  4.      <property name="hibernate.search.default.indexBase">  
  5.      D:\data\indexs  
  6.      </property>  
<property name="hibernate.search.default.directory_provider">
	org.hibernate.search.store.FSDirectoryProvider
     </property>
     <property name="hibernate.search.default.indexBase">
	 D:\data\indexs
     </property>

 

     到这里,配置和修改就已经完成了。当对象被插入,修改或删除的时候,将会出发索引的修改。
    
      如果你想对数据库中已有的数据建立索引可以

   

Java代码 复制代码  收藏代码
  1.      public class IndexBuilder {  
  2.     static Logger log = Logger.getLogger("IndexBuilder");  
  3.   
  4.     public static void main(String[] args) {  
  5.         Session session = null;  
  6.         try {  
  7.                         //配置文件  
  8.             ApplicationContext cxt = new FileSystemXmlApplicationContext(  
  9.                     "..\\WEB-INF\\applicationContext.xml");  
  10.             SessionFactory sessionFactory = (SessionFactory) cxt  
  11.                     .getBean("sessionFactory");  
  12.             session = sessionFactory.openSession();  
  13.             FullTextSession fullTextSession = Search  
  14.                     .createFullTextSession(session);  
  15.             Query query = session.createQuery("from Book")  
  16.                     .setMaxResults(1000);  
  17.             SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  18.             int j = 0;  
  19.             int sum = 0;  
  20.             log.info("start Indexing at "+df.format(Calendar.getInstance().getTimeInMillis()));  
  21.             while (true) {  
  22.                 session.getTransaction().begin();  
  23.                 List<PvmsMaterialProgram> list = query.setFirstResult(j).list();  
  24.                 for (PvmsMaterialProgram program : list) {  
  25.                     fullTextSession.index(program);  
  26.                 }  
  27.                 session.getTransaction().commit();  
  28.                 j += 1000;  
  29.                 if (list.size() < 1000)  
  30.                     break;  
  31.                 sum += list.size();  
  32.                 log.info("finish " + sum + " records");  
  33.             }  
  34.             log.info("end at "+df.format(Calendar.getInstance().getTimeInMillis()));  
  35.         } catch (Exception e) {  
  36.             e.printStackTrace();  
  37.         } finally {  
  38.             if (session != null)  
  39.                 session.close();  
  40.         }  
  41.     }  
  42. }  
  43.         
     public class IndexBuilder {
	static Logger log = Logger.getLogger("IndexBuilder");

	public static void main(String[] args) {
		Session session = null;
		try {
                        //配置文件
			ApplicationContext cxt = new FileSystemXmlApplicationContext(
					"..\\WEB-INF\\applicationContext.xml");
			SessionFactory sessionFactory = (SessionFactory) cxt
					.getBean("sessionFactory");
			session = sessionFactory.openSession();
			FullTextSession fullTextSession = Search
					.createFullTextSession(session);
			Query query = session.createQuery("from Book")
					.setMaxResults(1000);
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			int j = 0;
			int sum = 0;
			log.info("start Indexing at "+df.format(Calendar.getInstance().getTimeInMillis()));
			while (true) {
				session.getTransaction().begin();
				List<PvmsMaterialProgram> list = query.setFirstResult(j).list();
				for (PvmsMaterialProgram program : list) {
					fullTextSession.index(program);
				}
				session.getTransaction().commit();
				j += 1000;
				if (list.size() < 1000)
					break;
				sum += list.size();
				log.info("finish " + sum + " records");
			}
			log.info("end at "+df.format(Calendar.getInstance().getTimeInMillis()));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (session != null)
				session.close();
		}
	}
}
      


     
      这里每一千条会提交一次。如果出现内存溢出,可以把虚拟机的内存调大一些。
     

      索引构建好了,就可以开始使用查询功能了。Hibernate search支持复杂检索 - 支持Wild Card(诸如*, ?等通配符号),多关键字,模糊查询,排序等。可以使用封装好的接口也可以调用底层的lucene接口(参考官方的手册)。

      

Java代码 复制代码  收藏代码
  1.        session = sessionFactory.getCurrentSession();  
  2. tx = session.beginTransaction();  
  3.        String keyword = "足球"  
  4. FullTextSession fullTextSession = Search.createFullTextSession(session);  
  5.        //这里同时对title和摘要字段进行检索  
  6.        String[] fields = { "title""summarize" };  
  7. String[] values = { keyword, keyword};  
  8. MultiFieldQueryParser parser = new MultiFieldQueryParser(  
  9.     org.apache.lucene.util.Version.LUCENE_30, fields,new MMSegAnalyzer());  
  10.     org.apache.lucene.search.Query luceneQuery = parser.parse(  
  11.           org.apache.lucene.util.Version.LUCENE_30, values, fields,new MMSegAnalyzer());  
  12.               //按发布时间排倒序  
  13.         org.apache.lucene.search.Sort sort = new Sort(new SortField(  
  14.                 "publishDate", SortField.LONG, true));  
  15.   
  16. FullTextQuery hibQuery = fullTextSession.createFullTextQuery(luceneQuery, Book.class);  
  17.        //  
  18. hibQuery.setSort(sort);  
  19.       //分页设置  
  20. hibQuery.setFirstResult(start);  
  21. hibQuery.setMaxResults(limit);  
  22. tx.commit();  
  23. // log.info("query list = "+hibQuery.list());  
  24. List books = hibQuery.list();       
  25.         
        session = sessionFactory.getCurrentSession();
	tx = session.beginTransaction();
        String keyword = "足球"
	FullTextSession fullTextSession = Search.createFullTextSession(session);
        //这里同时对title和摘要字段进行检索
        String[] fields = { "title", "summarize" };
	String[] values = { keyword, keyword};
	MultiFieldQueryParser parser = new MultiFieldQueryParser(
		org.apache.lucene.util.Version.LUCENE_30, fields,new MMSegAnalyzer());
		org.apache.lucene.search.Query luceneQuery = parser.parse(
		      org.apache.lucene.util.Version.LUCENE_30, values, fields,new MMSegAnalyzer());
               //按发布时间排倒序
	        org.apache.lucene.search.Sort sort = new Sort(new SortField(
					"publishDate", SortField.LONG, true));

	FullTextQuery hibQuery = fullTextSession.createFullTextQuery(luceneQuery, Book.class);
        //
	hibQuery.setSort(sort);
       //分页设置
	hibQuery.setFirstResult(start);
	hibQuery.setMaxResults(limit);
	tx.commit();
	// log.info("query list = "+hibQuery.list());
	List books = hibQuery.list();     
       



       这里对title和summarize字段检索关键词"足球",并采取分页查询的策略。

       重建索引也非常简单

       

Java代码 复制代码  收藏代码
  1.       FullTextSession fullTextSession = Search              .getFullTextSession(sessionFactory.getCurrentSession());  
  2.        //异步  
  3. fullTextSession.createIndexer().start();  
  4.         //同步  
  5.        //fullTextSession.createIndexer().startAndwait();  
  6.       

猜你喜欢

转载自jetway.iteye.com/blog/2101374