Hibernate Search(基于version3.4)

来源:互联网 发布:软件测试工程师教程 编辑:程序博客网 时间:2024/05/17 07:02

Getting Start

 

1.1系统配置要求

java runtimeJDK或JRE5以上版本 Hibernate Search hibernate-search-3.4.0.Final.jar及其所需依赖。可通过Jboss Maven仓库下载(http://repository.jboss.org/
nexus/content/groups/public-jboss/ )Hibernate Core 3.4版本的Hibernate Search与3.6版本的Hibernate Core测试良好JPA2 虽然Hinbernate Search没有用到JPA,但Hibernate的持久化必须要用到JPA(如@Entity等)

 

1.2通过Maven配置依赖

1.2.1添加Jboss Maven仓库

Xml代码  收藏代码
  1. <settings>  
  2.   ...  
  3.   <profiles>  
  4.     ...  
  5.     <profile>  
  6.       <id>jboss-public-repository</id>  
  7.       <repositories>  
  8.         <repository>  
  9.           <id>jboss-public-repository-group</id>  
  10.           <name>JBoss Public Maven Repository Group</name>  
  11.           <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>  
  12.           <layout>default</layout>  
  13.           <releases>  
  14.             <enabled>true</enabled>  
  15.             <updatePolicy>never</updatePolicy>  
  16.           </releases>  
  17.           <snapshots>  
  18.             <enabled>true</enabled>  
  19.             <updatePolicy>never</updatePolicy>  
  20.           </snapshots>  
  21.         </repository>  
  22.       </repositories>  
  23.       <pluginRepositories>  
  24.         <pluginRepository>  
  25.           <id>jboss-public-repository-group</id>  
  26.           <name>JBoss Public Maven Repository Group</name>  
  27.           <url>https://repository.jboss.org/nexus/content/groups/public-jboss/</url>  
  28.           <layout>default</layout>  
  29.           <releases>  
  30.             <enabled>true</enabled>  
  31.             <updatePolicy>never</updatePolicy>  
  32.           </releases>  
  33.           <snapshots>  
  34.             <enabled>true</enabled>  
  35.             <updatePolicy>never</updatePolicy>  
  36.           </snapshots>  
  37.         </pluginRepository>  
  38.       </pluginRepositories>  
  39.     </profile>  
  40.   </profiles>  
  41.   <activeProfiles>  
  42.     <activeProfile>jboss-public-repository</activeProfile>  
  43.   </activeProfiles>  
  44.   ...  
  45. </setting>  

 

 

1.2.2在Maven应用中添加依赖

Xml代码  收藏代码
  1. <!--实际上只需要hibernate-search就足够了,因为maven会根据传递性依赖原则添加其他依赖,像hibnerate-core等等-->  
  2. <dependency>  
  3.    <groupId>org.hibernate</groupId>  
  4.    <artifactId>hibernate-search</artifactId>  
  5.    <version>3.4.0.Final</version>  
  6. </dependency>  
  7. <!--当需要用到hibernate-entitymanager时添加-->  
  8.  <dependency>  
  9.    <groupId>org.hibernate</groupId>  
  10.    <artifactId>hibernate-entitymanager</artifactId>  
  11.    <version>3.6.3.Final</version>  
  12. </dependency>  

 

1.3hibernate.cfg.xml或persistence.xml配置

Xml代码  收藏代码
  1. ...  
  2. <property name="hibernate.search.default.directory_provider"   
  3.           value="filesystem"/>   
  4. <property name="hibernate.search.default.indexBase"   
  5.           value="/var/lucene/indexes"/>  
  6. ...  

 属性hibernate.search.default.directory_provider告诉hibernate使用哪个DirectoryProvider实现。在Apache Lucene中有一个概念Directory来保存Index Files。Hibernate通过DirectoryProvider来初始化和配置一个Lucene Directory实例。在本例中,我们使用一个能把Index Files保存在file system中的DirectoryProvider。当Index Files保存在file system中时,我们可以通过Luke工具实时查看Lucene索引文件。除了DirectoryProvider外,还需要告诉hibernate索引文件保存在哪个具体的目录中,这通过hibernate.search.default.indexBase属性来配置。

 

我们假设有两个由hibernate持久的类文件example.Book和example.Author,并且想要为该应用添加全文搜索能力。请看下面样例:

 

Java代码  收藏代码
  1. package example;  
  2. ...  
  3. @Entity  
  4. @Indexed  
  5. public class Book {  
  6.   @Id  
  7.   @GeneratedValue  
  8.   private Integer id;  
  9.     
  10.   @Field(index=Index.TOKENIZED, store=Store.NO)  
  11.   private String title;  
  12.     
  13.   @Field(index=Index.TOKENIZED, store=Store.NO)  
  14.   private String subtitle;   
  15.   @IndexedEmbedded  
  16.   @ManyToMany   
  17.   private Set<Author> authors = new HashSet<Author>();  
  18.   @Field(index = Index.UN_TOKENIZED, store = Store.YES)  
  19.   @DateBridge(resolution = Resolution.DAY)  
  20.   private Date publicationDate;  
  21.     
  22.   public Book() {  
  23.   }   
  24.     
  25.   // standard getters/setters follow here  
  26.   ...   
  27. }  
 
Java代码  收藏代码
  1. package example;  
  2. ...  
  3. @Entity  
  4. public class Author {  
  5.   @Id  
  6.   @GeneratedValue  
  7.   private Integer id;  
  8.   @Field(index=Index.TOKENIZED, store=Store.NO)  
  9.   private String name;  
  10.   public Author() {  
  11.   }   
  12.    
  13.   // standard getters/setters follow here  
  14.   ...  
  15. }  

 

@Indexed:标注Book是可索引的。

@DocumentId:主键标注,当有@Id时可省略

@Field:标注哪些域是可搜索的。其中index=Index.TOKENIZED参数说明可以通过Analyzer解析,store=Store.NO参数说明是否在索引文件中保存该域的值。

Note :无论store=Store.NO还是store=Store.YES都不会影响最终的搜索能力。store.YES的作用是可以在搜索后可以直接从索引中获取域的完整值。在hibernate中,如果store=Store.NO,搜索结果中,域的值是通过数据库中获取,如果store=Store.YES,域的值是直接从索引文档中获取。

@DateBridge:因为Lucene只支持纯字符串的索引(Lucene2.9后支持数值索引),基于这样的原因,hibernate必须把Date类型的值转换成字符串

@IndexedEmbedded:该注解用于建立关联实体的索引。这是必须的,因为Lucene的索引文档是一种平整的数据结构,它不像数据库那样支持对象关联。为了确保author的名字可搜索,必须把author的名字作为Book索引文档的一个域。

 

1.4建立索引

Hibernate会在进行实体持久化,更新,删除操作时自动地建立索引。但是,你还必须为已经存在于数据库中的数据建立索引。下面的例子基于上面的配置和持久化类,展示了如何进行初始化索引。

Java代码  收藏代码
  1. //使用Hibernate Session初始化索引  
  2. FullTextSession fullTextSession = Search.getFullTextSession(session);  
  3. fullTextSession.createIndexer().startAndWait();  
 
Java代码  收藏代码
  1. //使用JPA初始化索引  
  2. EntityManager em = entityManagerFactory.createEntityManager();  
  3. FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);  
  4. fullTextEntityManager.createIndexer().startAndWait();  
 

运行了上面的代码后,你会在/var/lucene/indexes/中找到example.Book索引文件,你可能使用Luke查看索引文件,这可以帮助你更好地理解Hibernate Search。

 

1.5.建立搜索

有两种方法可以建立搜索,一种是直接使用Lucene的API,另一种是使用Hibernate Search query DSL。后者可以被包装成org.hibernate.Query,从而可以使用Hibernate API的机能。

 

通过Hibernate Session创建和运行搜索

Java代码  收藏代码
  1. FullTextSession fullTextSession = Search.getFullTextSession(session);  
  2. Transaction tx = fullTextSession.beginTransaction();  
  3. // create native Lucene query unsing the query DSL  
  4. // alternatively you can write the Lucene query using the Lucene query parser  
  5. // or the Lucene programmatic API. The Hibernate Search DSL is recommended though  
  6. QueryBuilder qb = fullTextSession.getSearchFactory()  
  7.     .buildQueryBuilder().forEntity( Book.class ).get();  
  8. org.apache.lucene.search.Query query = qb  
  9.   .keyword()  
  10.   .onFields("title""subtitle""authors.name""publicationDate")  
  11.   .matching("Java rocks!")  
  12.  .createQuery();  
  13. // wrap Lucene query in a org.hibernate.Query  
  14. org.hibernate.Query hibQuery =   
  15.     fullTextSession.createFullTextQuery(query, Book.class);  
  16. // execute search  
  17. List result = hibQuery.list();  
  18.     
  19. tx.commit();  
  20. session.close();  
 

通过JPA创建和运行搜索

Java代码  收藏代码
  1. EntityManager em = entityManagerFactory.createEntityManager();  
  2. FullTextEntityManager fullTextEntityManager =   
  3.     org.hibernate.search.jpa.Search.getFullTextEntityManager(em);  
  4. em.getTransaction().begin();  
  5. // create native Lucene query unsing the query DSL  
  6. // alternatively you can write the Lucene query using the Lucene query parser  
  7. // or the Lucene programmatic API. The Hibernate Search DSL is recommended though  
  8. QueryBuilder qb = fullTextSession.getSearchFactory()  
  9.     .buildQueryBuilder().forEntity( Book.class ).get();  
  10. org.apache.lucene.search.Query query = qb  
  11.   .keyword()  
  12.   .onFields("title""subtitle""authors.name""publicationDate")  
  13.   .matching("Java rocks!");  
  14.   .createQuery();  
  15. // wrap Lucene query in a javax.persistence.Query  
  16. javax.persistence.Query persistenceQuery =   
  17.     fullTextEntityManager.createFullTextQuery(query, Book.class);  
  18. // execute search  
  19. List result = persistenceQuery.getResultList();  
  20. em.getTransaction().commit();  
  21. em.close();   
 

1.6 Analyzer(解析器)

  Analyzer指定了按怎么样的规则去分词,比如词干分析("refactor", "refactors", "refactored" and "refactoring"都会是被认为是同一个词),是否去掉一些stop words(a,an,the)等等。Hibernate提供了几种方式去配置analyzer。

  • 在配置文件中配置 hibernate.search.analyzer属性。这里配置的analyzer是默认的解析器。
  • 在类级别中添加注解@Analyzer
  • 在域级别添加注解@Analyzer

在@Analyzer注解可以指定完全限定名,也可以是一个由@AnalyzerDef定义的analyzer的引用名。后一种方式会利用Solr Analyzer Framework的工厂方法。你可以通过查看Solr JavaDoc 或查看Solr Wiki相关段落找到更多可用的工厂方法。

 

在下面的例子中,StandardTokenizerFactory首先经过两个过滤器工厂(filter factories)过滤:LowerCaseFilterFactory 和 SnowballPorterFilterFactory。StandardTokenizerFactory通过标点与‘-’来划分词语,但保留像email,internet地址的完整性。LowerCaseFilterFactory把字母统一变成小写,而SnowballPorterFilterFactory处理指定语言的词干分析。

 

一般地,使用Solr Framework需要先定义一个tokenizer,之后是任意数量的filter。

 

使用@AnalyzerDef和Solr Framework定义和使用Analyzer

Java代码  收藏代码
  1. @Entity  
  2. @Indexed  
  3. @AnalyzerDef(name = "customanalyzer",  
  4.   tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),  
  5.   filters = {  
  6.     @TokenFilterDef(factory = LowerCaseFilterFactory.class),  
  7.     @TokenFilterDef(factory = SnowballPorterFilterFactory.class, params = {  
  8.       @Parameter(name = "language", value = "English")  
  9.     })  
  10.   })  
  11. public class Book {  
  12.   @Id  
  13.   @GeneratedValue  
  14.   @DocumentId  
  15.   private Integer id;  
  16.     
  17.   @Field(index=Index.TOKENIZED, store=Store.NO)  
  18.   @Analyzer(definition = "customanalyzer")  
  19.   private String title;  
  20.     
  21.   @Field(index=Index.TOKENIZED, store=Store.NO)  
  22.   @Analyzer(definition = "customanalyzer")  
  23.   private String subtitle;   
  24.   @IndexedEmbedded  
  25.   @ManyToMany   
  26.   private Set<Author> authors = new HashSet<Author>();  
  27.   @Field(index = Index.UN_TOKENIZED, store = Store.YES)  
  28.   @DateBridge(resolution = Resolution.DAY)  
  29.  private Date publicationDate;  
  30.     
  31.   public Book() {  
  32.   }   
  33.     
  34.   // standard getters/setters follow here  
  35.   ...   
  36. }  
0 0