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包添加到你的项目中。
     
      新建一个领域模型
       
     

      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;  
    }  
      
}  
        
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注解
     

     //索引名称  
     @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;  
}  
//索引名称
      @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节中加入

<property name="hibernate.search.default.directory_provider">  
    org.hibernate.search.store.FSDirectoryProvider  
     </property>  
     <property name="hibernate.search.default.indexBase">  
     D:\data\indexs  
     </property>  
<property name="hibernate.search.default.directory_provider">
	org.hibernate.search.store.FSDirectoryProvider
     </property>
     <property name="hibernate.search.default.indexBase">
	 D:\data\indexs
     </property>

 

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

   

     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();  
        }  
    }  
}  
        
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接口(参考官方的手册)。

      

       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();       
        
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字段检索关键词"足球",并采取分页查询的策略。

       重建索引也非常简单

       

      FullTextSession fullTextSession = Search              .getFullTextSession(sessionFactory.getCurrentSession());  
       //异步  
fullTextSession.createIndexer().start();  
        //同步  
       //fullTextSession.createIndexer().startAndwait();  
      

相关推荐