SeamFramework.orgCommunity Documentation
Full text search engines like Apache Lucene™ are a very powerful technology that bring full text and efficient queries to applications. Hibernate Search, which uses Apache Lucene under the covers, indexes your domain model with the addition of a few annotations, takes care of the database / index synchronization and returns regular managed objects that are matched by full text queries. Keep in mind, thought, that there are mismatches that arise when dealing with an object domain model over a text index (keeping the index up to date, mismatch between the index structure and the domain model, and querying mismatch). But the benefits of speed and efficiency far outweigh these limitations.
Hibernate Search has been designed to integrates nicely and as naturally as possible with JPA and Hibernate. As a natural extension, JBoss Seam provides an Hibernate Search integration.
Please refer to the Hibernate Search documentation for information specific to the Hibernate Search project.
Hibernate Search is configured either in the
META-INF/persistence.xml
or
hibernate.cfg.xml
file.
Hibernate Search configuration has sensible defaults for most configuration parameters. Here is a minimal persistence unit configuration to get started.
<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>
If you plan to target Hibernate Annotations or EntityManager 3.2.x (embedded into JBoss AS 4.2.GA), you also need to configure the appropriate event listeners.
<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>
This step is no longer necessary if Hibernate Annotation or EntityManager 3.3.x are used.
In addition to the configuration file, the following jars have to be deployed:
hibernate-search.jar
hibernate-commons-annotations.jar
lucene-core.jar
If you deploy those in a EAR, don't forget to update
application.xml
Hibernate Search uses annotations to map entities to a Lucene index, check the reference documentation for more informations.
Hibernate Search is fully integrated with the API and semantic of
JPA / Hibernate. Switching from a HQL or Criteria based query requires
just a few lines of code. The main API the application interacts with is
the FullTextSession
API (subclass of Hibernate's
Session
).
When Hibernate Search is present, JBoss Seam injects a
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
extends
org.hibernate.Session
so that it can be used as a
regular Hibernate Session
If the Java Persistence API is used, a smoother integration is proposed.
@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();
}
[...]
}
When Hibernate Search is present, a
FulltextEntityManager
is injected.
FullTextEntityManager
extends
EntityManager
with search specific methods, the
same way FullTextSession
extends
Session
.
When an EJB 3.0 Session or Message Driven Bean injection is used (i.e.
via the @PersistenceContext annotation), it is not possible to replace the
EntityManager
interface by the
FullTextEntityManager
interface in the declaration
statement. However, the implementation injected will be a
FullTextEntityManager
implementation: downcasting
is then possible.
@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();
}
[...]
}
For people accustomed to Hibernate Search out of Seam, note that
using Search.createFullTextSession
is not
necessary.
Check the DVDStore or the blog examples of the JBoss Seam distribution for a concrete use of Hibernate Search.