28.1. 介绍
如Apache Lucene? 之类的全文本搜索引擎是一种非常强大的技术,给应用程序带来了全文本和有效的查询。 Hibernate搜索,其使用了受保护的Apache Lucene, 用附加的几个注释索引你的域模型,关注数据库/索引同步,并且返回与全文本查询相匹配的标准的托管对象。请记住,思考,存在的不匹配,当在一个文本查询之上处理一个对象的域模型时引发的不匹配(保持数据的最新索引,索引结构与域模型的不匹配,查询不匹配)。但是,快速有效的好处远远地超过了这些局限性。
Hibernate搜索旨在很好地整合,并尽可能自然地使用JPA和Hibernate。作为一个自然延伸,JBoss Seam提供了一个Hibernate搜索集成。
Hibernate搜索对象的详细信息,请参考Hibernate搜索文档 。
28.2. 配置
Hibernate搜索使用META-INF/persistence.xml或hibernate.cfg.xml 文件进行配置
Hibernate搜索配置对大多数配置参数存在智能默认 。这里是一个入门的最小的持久化单元配置。
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
[...]
<!—使用一个基于索引的文件系统 -->
<property name="hibernate.search.default.directory_provider"
value="org.hibernate.search.store.FSDirectoryProvider"/>
<!—索引将被存储的目录 -->
<property name="hibernate.search.default.indexBase"
value="/Users/prod/apps/dvdstore/dvdindexes"/>
</properties>
</persistence-unit>
如果你打算瞄准Hibernate注释或EntityManager 3.2.x (嵌于JBoss AS 4.2.GA内部的), 你也需要配置适当的事件侦听器。
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
[...]
<!-- 使用一个基于索引的文件系统 -->
<property name="hibernate.search.default.directory_provider"
value="org.hibernate.search.store.FSDirectoryProvider"/>
<!-- 索引将被存储的目录 -->
<property name="hibernate.search.default.indexBase"
value="/Users/prod/apps/dvdstore/dvdindexes"/>
<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"/>
</properties>
</persistence-unit>
注意
如果使用的是Hibernate注释或EntityManager 3.3.x,这步就不再需要了。
除了配置文件之外,下面的jar包必须被部署:
- hibernate-search.jar
- hibernate-commons-annotations.jar
- lucene-core.jar
注意
如果你在一个EAR中部署了它们,不要忘了更新application.xml。
28.3. 用法
Hibernate搜索使用注释映射实体到一个Lucene索引,详情请查参考文档 。
Hibernate搜索完全整合了API和JPA/Hibernate语义。 仅几行代码,就可以从一个HQL或基于查询请求的条件(Criteria)进行转换。与应用程序交互的主要API是FullTextSession API(Hibernate会话的子类 Session)。
当Hibernate搜索被引入, JBoss Seam就可注入一个FullTextSession。
@Stateful
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable {
@In FullTextSession session;
public void search(String searchString) {
org.apache.lucene.search.Query luceneQuery = getLuceneQuery();
org.hibernate.Query query session.createFullTextQuery(luceneQuery, Product.class);
searchResults = query
.setMaxResults(pageSize + 1)
.setFirstResult(pageSize * currentPage)
.list();
}
[...]
}
注意
FullTextSession继承了org.hibernate.Session,所以,它可以被用来作为一个标准的Hibernate会话。
如果使用Java持久化API, 一个更流畅的集成被提议。
@Stateful
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable {
@In FullTextEntityManager em;
public void search(String searchString) {
org.apache.lucene.search.Query luceneQuery = getLuceneQuery();
javax.persistence.Query query = em.createFullTextQuery(luceneQuery, Product.class);
searchResults = query
.setMaxResults(pageSize + 1)
.setFirstResult(pageSize * currentPage)
.getResultList();
}
[...]
}
当Hibernate搜索被引入,就可注入一个FulltextEntityManager。FullTextEntityManager 继承了EntityManager的搜索特殊方法, 以同样的方式FullTextSession继承了会话 。
当使用EJB 3.0 会话或消息驱动Bean注入 (如,通过@PersistenceContext 注释), 在声明语句中用FullTextEntityManager接口替换EntityManager接口是不可能的。然而,注入实现可以是FullTextEntityManager实现:向下转型就可以了。
@Stateful
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable {
@PersistenceContext EntityManager em;
public void search(String searchString) {
org.apache.lucene.search.Query luceneQuery = getLuceneQuery();
FullTextEntityManager ftEm = (FullTextEntityManager) em;
javax.persistence.Query query = ftEm.createFullTextQuery(luceneQuery, Product.class);
searchResults = query
.setMaxResults(pageSize + 1)
.setFirstResult(pageSize * currentPage)
.getResultList();
}
[...]
}
警告
对于习惯在Seam之外使用Hibernate搜索的人,注意, 使用Search.createFullTextSession 是没有必要的。
Hibernate搜索的具体应用请查看JBoss Seam 发布的DVDStore 或者blog例子 。