Hibernate Search Example
— print (last updated: Nov 14, 2009) print

Select font size:
This project is a non-GUI application intended to illustrate the Hibernate search mechanisms. It assumes that you have already installed and run the SwingNotes project from the Swing Notes Project document, so that the swingnotes MySQL database is viable. The support files, including the models package as well as the XML configuration files are identical to those in that project.

Download the HibernateSearchExample.zip archive and install it as a Java Project with Existing Sources with project name HibernateSearchExample. Add the MySQL Driver and HibernateSearch libraries to the project and run it. The word "object" is a good choice for search keyword.

Fulltext search

Fulltext search is a well-known method which achieves its speed on large documents by an indexing technique. A keyword search is normally meant to match against the the keyword's presence in the text as an complete word (in a case-insensitive manner), not a substring of a longer word. Certain common English words, like "a", "an", "the" are ignored in the search indexing.

MySQL native fulltext search

MySQL, per se, permits fulltext search on its tables using a table declaration something like this:
create table ... (
  content text not null,
  ...
  fulltext(content),
  ...
) type=myisam;
The fulltext declaration is necessary and the type=myisam may be necessary, depending on the MySQL installation details. Record selection based upon matching a given keyword within the content field is most commonly done like this:
SELECT ... WHERE MATCH(content) AGAINST ('keyword' IN BOOLEAN MODE);

Hibernate fulltext search

Hibernate's fulltext search method does not use any of the DBMS's native fulltext search capability. Instead, it is based on fulltext search drivers from the Java open source Lucene code:
http://lucene.apache.org/
One of the key features with this search method is the presence of a directory, indexes, which serves as persistent storage (effectively, an extension of the database). It is used for indexing the content field of Notes. This directory is specified by the hibernate.cfg.xml property setting:
<property name="hibernate.search.default.indexBase">indexes</property>
Any pre-created Notes (such as those created by the table-data.sql file) need to to be explicity indexed as is done in this example program. Otherwise, the indexing takes place automatically for Update, Insert and Delete operations by virtue of the three event element specifications in hibernate.cfg.xml.

Main program


hibernatesearchexample.Main
package hibernatesearchexample; import org.hibernate.*; import org.hibernate.search.FullTextSession; import org.hibernate.search.Search; import org.apache.lucene.queryParser.*; import org.apache.lucene.analysis.standard.StandardAnalyzer; import java.util.List; import models.*; public class Main { public static void main(String[] args) { DB db = new DB(); // Index pre-existing database elements is only necessary for // records which were NOT created by Hibernate's // insert, delete and update operations System.out.println("Indexing pre-existing elements"); Session sess = db.getSession(); List<Note> notes = sess.createCriteria(Note.class).list(); FullTextSession ftsess = Search.getFullTextSession(sess); ftsess.getTransaction().begin(); for (Note note : notes) { ftsess.index(note); } ftsess.getTransaction().commit(); // obtain the search key and define the Lucene parser String[] fields = new String[]{"content"}; QueryParser parser = new MultiFieldQueryParser(fields, new StandardAnalyzer()); String key = javax.swing.JOptionPane.showInputDialog("Enter search key"); if (key == null) { // dialog was cancelled System.exit(1); } key = key.trim(); org.apache.lucene.search.Query lquery = null; try { lquery = parser.parse(key); } catch (Exception x) { x.printStackTrace(); System.exit(1); } // create the Hibernate search query as a wrapper around // the Lucene query sess = db.getSession(); ftsess = Search.getFullTextSession(sess); org.hibernate.Query hquery = ftsess.createFullTextQuery(lquery, Note.class); List<Note> results = hquery.list(); // execute the query System.out.println("\n# matching records: " + results.size()); for (Note note : results) { System.out.println("\n" + note); } System.exit(0); } }


© Robert M. Kline