官方介绍:
Hibernate Search brings the power of full text search engines to the persistence domain model and Hibernate experience, through transparent configuration (Hibernate Annotations) and a common API.
Full text search engines like Apache Lucene(tm) allow applications to execute free-text search queries. However, it becomes increasingly more difficult to index a more complex object domain model - keeping the index up to date, dealing with the mismatch between the index structure and the domain model, querying mismatches, and so on.
Hibernate Search abstracts you from these problems by solving:
The structural mismatch: Hibernate Search takes care of the object/index translation
The duplication mismatch: Hibernate Search manages the index, keeps changes synchronized with your database, and optimizes the index access transparently
The API mismatch: Hibernate Search lets you query the index and retrieve managed objects as any regluar Hibernate query would do
Hibernate Search is using Apache Lucene(tm) internally, and always provides the ability to fallback to the native Lucene APIs.
Depending on application needs, Hibernate Search works well in non-clustered and clustered mode, provides synchronous index updates and asynchronous index updates, letting you choose between response time, throughput and index update.
Hibernate Search项目的主要特性包含以下几个方面:
- Lucene集成——作为强大高效的检索引擎,Lucene的美名早已久经考验了;
- 数据的自动插入和更新——当一个对象通过Hibernate添加或更新时,索引也会相应进行透明的更新;
- 支持众多复杂的搜索方式——可快速的使用通配符进行搜索,以及多关键词全文检索(multi-word text searches)和近似或同义词搜索(approximation/synonym searches),或根据相关性排列搜索结果;
- 搜索集群(Search Clustering)——Hibernate Search提供了内建搜索集群解决方案,其中包括一个基于JMS的异步查询和索引系统;
- 对Lucene API接口的直接调用——如果用户打算处理某些特别复杂的问题,可以在查询中直接使用Lucene提供的API接口;
- 对Lucene的自动管理——Hibernate Search可以管理并优化Lucene的索引,并且非常高效地使用Lucene的API接口。
Hibernate Search相关的Annotation主要有三个:
- @Indexed 标识需要进行索引的对象,
属性 : index 指定索引文件的路径
- @DocumentId 用于标示实体类中的唯一的属性保存在索引文件中,是当进行全文检索时可以这个唯一的属性来区分索引中其他实体对象,一般使用实体类中的主键属性
- @Field 标注在类的get属性上,标识一个索引的Field
属性 : index 指定是否索引,与Lucene相同
store 指定是否索引,与Lucene相同
name 指定Field的name,默认为类属性的名称
analyzer 指定分析器
另外@IndexedEmbedded 与 @ContainedIn 用于关联类之间的索引
@IndexedEmbedded有两个属性,一个prefix指定关联的前缀,一个depth指定关联的深度
step-by-step实例:
1.在maven的pom.xml文件中加入以下三个依赖包:
.......
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search</artifactId>
<version>3.0.1.GA</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.0.ga</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.3.1.ga</version>
</dependency>
.......
2.hiberante配置文件
主要就是添加两个属性,hibernate.search.default.directory_provider指定Directory的代理,即把索引的文件保存在硬盘中(org.hibernate.search.store.FSDirectoryProvider)还是内存里(org.hibernate.search.store.RAMDirectoryProvider),保存在硬盘的话hibernate.search.default.indexBase属性指定索引保存的路径.
......
<!-- use a file system based index -->
<prop
key="hibernate.search.default.directory_provider">
org.hibernate.search.store.FSDirectoryProvider
</prop>
<!-- directory where the indexes will be stored -->
<prop key="hibernate.search.default.indexBase">
D:/index
</prop>
.........
如果计划使用Hibernate Annotations或者EntityManager 3.2.x(已经嵌入到JBoss AS 4.2.GA中),那也需要配置相应的事件监听器。
<!-- use a file system based index -->
<property name="hibernate.search.default.directory_provider"
value="org.hibernate.search.store.FSDirectoryProvider"/>
<!-- directory where the indexes will be stored -->
<property name="hibernate.search.default.indexBase"
value="D:/index"/>
<!--事件监听器-->
<property name="hibernate.ejb.event.post-insert"
value="org.hibernate.search.event.FullTextIndexEventListener"/>
<property name="hibernate.ejb.event.post-update"
value="org.hibernate.search.event.FullTextIndexEventListener"/>
<property name="hibernate.ejb.event.post-delete"
value="org.hibernate.search.event.FullTextIndexEventListener"/>
3.pojo
PromotionCase.java
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.hibernate.search.annotations.Analyzer;
import org.hibernate.search.annotations.DocumentId;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Index;
import org.hibernate.search.annotations.Indexed;
import org.hibernate.search.annotations.Store;
/**
* @author david.wei
*
*/
@Entity()
@Table(name = "promotioncase")
@Indexed(index = "promotionCase")
public class PromotionCase implements Serializable {
private Long id;
private String name;
private String content;
private Short type;
private Short state;
private Date beginTime;
private Date endTime;
// basic-->common
private List<PromotionCase> promotionCases;
@Id
@GeneratedValue
@DocumentId
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column(name = "name", length = 128)
@Field(name = "name", index = Index.TOKENIZED, store = Store.YES, analyzer = @Analyzer(impl = StandardAnalyzer.class))
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Column(name = "state", length = 50)
@Field(name = "state", index = Index.TOKENIZED, store = Store.YES, analyzer = @Analyzer(impl = StandardAnalyzer.class))
public Short getState() {
return state;
}
public void setState(Short state) {
this.state = state;
}
@Column(name = "type", length = 50)
public Short getType() {
return type;
}
public void setType(Short type) {
this.type = type;
}
@Column(name = "content", length = 256)
@Field(name = "content", index = Index.TOKENIZED, store = Store.YES, analyzer = @Analyzer(impl = StandardAnalyzer.class))
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Column(name = "begin_time", length = 256)
@Temporal(TemporalType.TIMESTAMP)
public Date getBeginTime() {
return beginTime;
}
public void setBeginTime(Date beginTime) {
this.beginTime = beginTime;
}
@Column(name = "end_time", length = 256)
@Temporal(TemporalType.TIMESTAMP)
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
@ManyToMany(fetch = FetchType.LAZY, targetEntity = PromotionCase.class)
@JoinTable(name = "promotionCase_ref", joinColumns = @JoinColumn(name = "normal_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "basic_id", referencedColumnName = "id"))
public List<PromotionCase> getPromotionCases() {
return promotionCases;
}
public void setPromotionCases(List<PromotionCase> promotionCases) {
this.promotionCases = promotionCases;
}
}
在这里是对name和content两个字段建立了索引。
完成了以上步骤,当对对象进行增删改的时候hibernate会去执行相应的索引创建、删除或修改。
4.搜索
FullTextSession fullTextSession = Search
.createFullTextSession(getPromotionCaseDao()
.getSessionFactory().openSession());
MultiFieldQueryParser parser = new MultiFieldQueryParser(new String[] {
"name", "content" }, new StandardAnalyzer());
org.apache.lucene.search.Query luceneQuery = parser.parse(indexString);
FullTextQuery query = fullTextSession.createFullTextQuery(luceneQuery,
PromotionCase.class);
// 添加分页查询
query.setFirstResult(3);
query.setMaxResults(80);
// 对查询结果按name进行排序
org.apache.lucene.search.Sort sort = new Sort(new SortField("name"));
query.setSort(sort);
List result = query.list();
简单的应用就是这么样子了.
项目开始了,这段时间有点忙,随便整理了一下.不是很全,研究的也不是很深入.等项目做完了再找个时间好好分析与整理下.