如Apache Lucene™ 之类的全文搜索引擎是一种非常强大的技术,给我们的应用程序带来了高效的文本查询。 在处理一个对象域模型的时候有可能会遇到多处不匹配(保持最新的索引,索引结构和域模型之间的不匹配,查询不匹配...) Hibernate Search根据一些注解来索引域模型、管理数据库与索引的同步,并从自由文本查询中带给你正常的受管对象。 Hiberante Search在目前的版本里使用了Apache Luncene。
Hibernate Search在设计之初就是要很好并且尽可能自然地集成JPA和Hibernate,因此自然而然的,JBoss Seam也就提供了Hibernate Search的集成。
请参考Hibernate Search项目文档信息 Hibernate Search documentation。
Hibernate Search既可以在 META-INF/persistence.xml 中也可以在 hibernate.cfg.xml 中进行配置。
对大多数配置参数来说,Hibernate Search配置为其提供合理的默认值,在这里有一个最小化配置的描述。
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
[...]
<!-- 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="/Users/prod/apps/dvdstore/dvdindexes"/>
</properties>
</persistence-unit>
如果计划使用Hibernate Annotations或者EntityManager 3.2.x(已经嵌入到JBoss AS 4.2.GA中),那也需要配置相应的事件监听器。
<persistence-unit name="sample">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
[...]
<!-- 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="/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>
Note | |
---|---|
如果是使用了Hibernate Annotation或者EntityManager 3.3.x,这一步就不再需要了。 |
除了配置文件之外,把下面的jars包需要部署到服务器中或者打包进入你的工程中:
hibernate-search.jar
hibernate-commons-annotations.jar
lucene-core.jar
Note | |
---|---|
如果部署的是一个EAR包,别忘了要更新 application.xml 文件 |
Hibernate Search使用注解来映射实体类给Lucene索引,访问 reference documentation 来获取更多的说明。
Hibernate Search完全集成JPA/Hibernate的API和语法。只需要几行代码,就可以在基于HQL或者Criteria的查询间进行切换。主API和应用程序是通过 FullTextSession API (Hibernate Session 的子类)相互交互的。
当有Hibernate Search的时候,JBoss Seam注入 FullTextSession 。
@Stateful
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable
{
@In
FullTextSession session;
public void search(String searchString) {
org.apache.lucene.query.Query luceneQuery = getLuceneQuery();
org.hibernate.Query query session.createFullTextQuery(luceneQuery, Product.class);
searchResults = query
.setMaxResults(pageSize + 1)
.setFirstResult(pageSize * currentPage)
.list();
}
[...]
}
Note | |
---|---|
FullTextSession 继承自 org.hibernate.Session,因此它可以被当作正常的Hibernate Session来使用。 |
如果使用Java Persistence API,建议做一个平滑的集成。
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable
{
@In
FullTextEntityManager em;
public void search(String searchString) {
org.apache.lucene.query.Query luceneQuery = getLuceneQuery();
javax.persistence.Query query = em.createFullTextQuery(luceneQuery, Product.class);
searchResults = query
.setMaxResults(pageSize + 1)
.setFirstResult(pageSize * currentPage)
.getResultList();
}
[...]
}
当有Hibernate Search的时候,FulltextEntityManager 被注入。 FullTextEntityManager 继承了 EntityManager 并带有特定的搜索方法, 同样 FullTextSession 继承了 Session。
当注入 EJB 3.0 Session 或者 Message Driven Bean 时(例如使用 @PersistenceContext 注解的Bean), 就不可能在定义声明中使用 FullTextEntityManager 接口来替换 EntityManager 接口。 然而,将注入一个 FullTextEntityManager 实现:进行类型转换后就可以了。
@Stateful
@Name("search")
public class FullTextSearchAction implements FullTextSearch, Serializable
{
@PersistenceContext
EntityManager em;
public void search(String searchString) {
org.apache.lucene.query.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();
}
[...]
}
Caution | |
---|---|
对于那些经习惯了在Seam之外使用Hibernate Search的人来说,要注意使用 Search.createFullTextSession 是不需要的了。 |
对于Hibernate Search更详细的示例用法,请查看JBoss Seam发行包中的DVDStore或者Blog示例。