Hibernate Search is a full text search engine

Hibernate Search is a full text search engine built using Apache Lucene framework. Hibernate Search indexes your domain model, keep the index upto date and also performs full text search functionality to fetch matching domain objects. This Hello World example shows how you can setup hibernate search and get your domain objects based on free text search query. In this tutorial we will use Maven tool to build the project, Eclipse IDE to code and SQLite database to save our domain objects.

To make the learning easier, I have used SQLite database which is a self-contained, serverless, zero-configuration, transactional SQL database engine. But you are free to choose any other database as well to learn this tutorial. To run example shown in this tutorial, you do not have to install any database or SQLite database seperately. However to browse the database you can use 'SQLite Manager - Firefox addon' which provides a very nice GUI for SQLite database.

Tools and Technologies used in this article :

  1. Hibernate Search 4.1

  2. Maven

  3. SQLite 3 database

  4. SQLite Manager - Firefox addon

  5. Eclipse 3.7

Download : 
  • Maven
  • SQLite Manager - Firefox addon
  • SQLite database

1. Create a Java Project using Maven Tool

In the command prompt execute the following command to generate Maven compatible Java project named as 'HibernateSearchHelloWorld'.

1
mvn archetype:generate -DgroupId=com.srccodes.example.hibernate -DartifactId=HibernateSearchHelloWorld -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Generated Maven Java Project structure
Hibernate Search is a full text search engine_第1张图片

 

2. Update pom.xml

Add dependency of Hibernate core and SQLite jdbc library. Also update 'maven-compiler-plugin' so that it uses compilation level 1.5 onwards. Otherwise annotation (introduced in JDK 5) will not work.

File : pom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<projectxmlns=" http://maven.apache.org/POM/4.0.0"xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation=" http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.srccodes.example.hibernate</groupId>
    <artifactId>HibernateSearchHelloWorld</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>HibernateSearchHelloWorld</name>
    <url> http://maven.apache.org</url>
    <dependencies>
        <!-- hibernate -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.4.Final</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-search</artifactId>
            <version>4.1.1.Final</version>
        </dependency>
 
        <!-- SQLite JDBC library -->
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.7.2</version>
        </dependency>
 
        <!-- junit test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.5</source>
                    <target>1.5</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

3. Convert to Eclipse compatible Java project

Open the directory 'HibernateSearchHelloWorld' in command prompt and run the following maven command.

1
mvn eclipse:eclipse
Screenshot of command prompt
Hibernate Search is a full text search engine_第2张图片

On completion of the above command, Maven Java project will be converted to a Eclipse compatible java project.

Eclipse compatible Java Project structure
Hibernate Search is a full text search engine_第3张图片

 

4. Import project in Eclipse

Open Eclipse IDE and select from the menu File --> Import --> General --> Existing Projects into Workspace

Hibernate Search is a full text search engine_第4张图片

Browse to the directory of the newly converted Eclipse compatible Java Project and click 'Finish' button.

Hibernate Search is a full text search engine_第5张图片
Screenshot of Eclipse project structure
Hibernate Search is a full text search engine_第6张图片

 

5. Add Hibernate Configuration file

Right click on 'main' and select from context menu 'New' --> 'Folder'.

Hibernate Search is a full text search engine_第7张图片

Enter 'resources' in the 'Folder name' field and click the 'Finish' button.

Hibernate Search is a full text search engine_第8张图片

Copy the 'hibernate.cfg.xml' file in the 'resources' folder.

File: hibernate.cfg.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
" http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
 
<hibernate-configuration>
    <session-factory>
        <propertyname="show_sql">false</property>
        <propertyname="format_sql">true</property>
        <propertyname="dialect">org.hibernate.dialect.SQLiteDialect</property>
        <propertyname="connection.driver_class">org.sqlite.JDBC</property>
        <propertyname="connection.url">jdbc:sqlite:mydb.db</property>
        <propertyname="connection.username"></property>
        <propertyname="connection.password"></property>
         
        <propertyname="hibernate.hbm2ddl.auto">update</property>
 
        <propertyname="hibernate.search.default.directory_provider">filesystem</property>
        <propertyname="hibernate.search.default.indexBase">C:\lucene\indexes</property>
         
        <mappingclass="com.srccodes.example.hibernate.Contact"/>
    </session-factory>
</hibernate-configuration>
Note : 
'mydb.db' is the SQLite database file included with the sourcecode attached in 'Download Source Code' section. You can create db file of your own using 'SQLite Manager - Firefox addon' UI. But copy that file inside 'HibernateSearchHelloWorld' project directory directly.

I have set the property 'hibernate.hbm2ddl.auto' to 'update' so that when you will execute the code it will create the database tables of it's own based on the entity class 'com.srccodes.example.hibernate.Contact') we have written and referenced in this configuration file.

Set property 'hibernate.search.default.indexBase' to a writeable directory where Lucene will create index for your domain objects.

 

6. Configure Java Build Path

Right click on 'HibernateSearchHelloWorld' project and select from context menu 'Properties' --> 'Java Build Path'.
Add 'resources' folder as shown in the screenshot below

Hibernate Search is a full text search engine_第9张图片

 

7. Add SQLiteDialect

Copy from attached source code or download SQLiteDialect and add under package 'org.hibernate.dialect' in your project.

Note : 
dialect is used to help hibernate framework to create underlying database specific SQL query.

 

8. Write Entity class

Create a class 'Contact' under the package 'com.srccodes.example.hibernate' and copy the following content.

File: Contact.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
packagecom.srccodes.example.hibernate;
 
importjavax.persistence.Entity;
importjavax.persistence.Id;
importjavax.persistence.Table;
 
importorg.hibernate.search.annotations.Analyze;
importorg.hibernate.search.annotations.Field;
importorg.hibernate.search.annotations.Index;
importorg.hibernate.search.annotations.Indexed;
importorg.hibernate.search.annotations.Store;
 
/**
 * The persistent class for the contact database table.
 *
 */
@Entity
@Indexed
@Table(name ="contact")
publicclassContact {
    privateInteger id;
    privateString name;
    privateString email;
 
    publicContact() {
 
    }
 
    publicContact(Integer id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
 
    @Id
    publicInteger getId() {
        returnthis.id;
    }
 
    publicvoidsetId(Integer id) {
        this.id = id;
    }
 
    @Field(index = Index.YES, analyze = Analyze.YES, store = Store.NO)
    publicString getName() {
        returnthis.name;
    }
 
    publicvoidsetName(String name) {
        this.name = name;
    }
 
    publicString getEmail() {
        returnemail;
    }
 
    publicvoidsetEmail(String email) {
        this.email = email;
    }
     
    @Override
    publicString toString() {
        StringBuilder stringBuilder =newStringBuilder("Id: ").append(this.getId()).append(" | Name:").append(this.getName()).append(" | Email:").append(this.getEmail());
         
        returnstringBuilder.toString();
    }
}
Note : 

To know basic hibernate annotation follow the tutorial Hibernate Hello World example using Maven build tool and SQLite database

@Indexed annotation specifies an entity as indexable.
@Field annotation specifies an field as searchable. Here Index.YES means 'name' field will indexed, Analyze.YES means that filed will be analyzed (excludes common stop words like 'a', 'an', 'and', 'the' etc) using default Lucene Analyzer, Store.NO means actual 'name' field data will not be stored in the index.

I have also written 'toString()' method which we'll use to print out domain objects in console.

 

9. Common utility class for Hibernate

Copy the following code to 'HibernateUtil' class of package 'com.srccodes.example.hibernate'.

File: HibernateUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
packagecom.srccodes.example.hibernate;
 
importjava.util.Properties;
 
importorg.hibernate.HibernateException;
importorg.hibernate.Session;
importorg.hibernate.SessionFactory;
importorg.hibernate.cfg.Configuration;
importorg.hibernate.service.ServiceRegistry;
importorg.hibernate.service.ServiceRegistryBuilder;
 
/**
 * Contains utility methods
 *
 * @author srccodes.com
 * @version 1.0
 *
 */
publicclassHibernateUtil {
     
    privatestaticSessionFactory sessionFactory =null; 
    privatestaticServiceRegistry serviceRegistry =null; 
       
    privatestaticSessionFactory configureSessionFactory()throwsHibernateException { 
        Configuration configuration =newConfiguration(); 
        configuration.configure(); 
         
        Properties properties = configuration.getProperties();
         
        serviceRegistry =newServiceRegistryBuilder().applySettings(properties).buildServiceRegistry();         
        sessionFactory = configuration.buildSessionFactory(serviceRegistry); 
         
        returnsessionFactory; 
    }
     
    // We need to configure session factory once.
    // Rest of the time we will get session using the same.
    static{
        configureSessionFactory();
    }
     
    privateHibernateUtil() {}
     
    publicstaticSession getSession() {
        returnsessionFactory.openSession();
    }
}
Note : 
'configureSessionFactory()' method will build the hibernate session factory based on the configuration in 'hibernet.cfg.xml' file.

'getSession()' method will provide a Hibernate session from the configured session factory.

 

10. Hibernate Search and Indexing code

Copy the following code to 'App' class of package 'com.srccodes.example.hibernate'.

File: App.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
packagecom.srccodes.example.hibernate;
 
importjava.util.List;
importjava.util.Scanner;
 
importorg.hibernate.Session;
importorg.hibernate.search.FullTextSession;
importorg.hibernate.search.Search;
importorg.hibernate.search.query.dsl.QueryBuilder;
 
/**
 * Hello world!
 *
 */
publicclassApp {
     
    privatestaticvoiddoIndex()throwsInterruptedException {
        Session session = HibernateUtil.getSession();
         
        FullTextSession fullTextSession = Search.getFullTextSession(session);
        fullTextSession.createIndexer().startAndWait();
         
        fullTextSession.close();
    }
     
    privatestaticList<Contact> search(String queryString) {
        Session session = HibernateUtil.getSession();
        FullTextSession fullTextSession = Search.getFullTextSession(session);
         
        QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Contact.class).get();
        org.apache.lucene.search.Query luceneQuery = queryBuilder.keyword().onFields("name").matching(queryString).createQuery();
 
        // wrap Lucene query in a javax.persistence.Query
        org.hibernate.Query fullTextQuery = fullTextSession.createFullTextQuery(luceneQuery, Contact.class);
         
        List<Contact> contactList = fullTextQuery.list();
         
        fullTextSession.close();
         
        returncontactList;
    }
     
    privatestaticvoiddisplayContactTableData() {
        Session session =null;
         
        try{
            session = HibernateUtil.getSession();
             
            // Fetching saved data
            List<Contact> contactList = session.createQuery("from Contact").list();
             
            for(Contact contact : contactList) {
                System.out.println(contact);
            }
             
        }catch(Exception ex) {
            ex.printStackTrace();
        }finally{
            if(session !=null) {
                session.close();
            }
        }
    }
     
    publicstaticvoidmain(String[] args)throwsInterruptedException {
        System.out.println("\n\n******Data stored in Contact table******\n");
        displayContactTableData();
         
        // Create an initial Lucene index for the data already present in the database
        doIndex();
         
        Scanner scanner =newScanner(System.in);
        String consoleInput =null;
         
        while(true) {
            // Prompt the user to enter query string
            System.out.print("\n\nEnter search key (To exit type 'X')");           
            consoleInput = scanner.nextLine();
             
            if("X".equalsIgnoreCase(consoleInput)) {
                System.out.println("End");
                System.exit(0);
            }  
             
            List<Contact> result = search(consoleInput);           
            System.out.println("\n\n>>>>>>Record found for '"+ consoleInput +"'");
             
            for(Contact contact : result) {
                System.out.println(contact);
            }              
        }          
    }
}
Note : 
'doIndex()' method will generate indexes for your domain objects in the directory specified in the 'hibernate.search.default.indexBase' property in 'hibernate.cfg.xml' file.

'search(String queryString)' method will prepare a Lucene search query based on the query string. Then that query will be wrapped in a javax.persistence.Query which will be executed to return matching domain objects.

 

11. Final project structure

After doing all the changes the overall project structure will look like this

Hibernate Search is a full text search engine_第10张图片

 

12. Populate 'Contact' table with data

Browse the 'mydb.db' SQLite database file (under 'HibernateSearchHelloWorld' project) using 'SQLite Manager - Firefox addon'. Populate the 'Contact' table with some dummy test data.

Screenshot of the table using 'SQLite Manager - Firefox addon' UI
Hibernate Search is a full text search engine_第11张图片

 

13. Run Your Code

Right click on 'App.java' and select from context menu 'Run As' --> 'Java Application'.

 

13. Console Output

In the console, all the records of the 'Contact' table will be printed first. Then you will be prompted to enter search key. Based on the search key Hibernate Search API will return all the matching domain objects which will be printed in the console. To exit from the command prompt you have to type 'X'.

Console
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
Id: 1 | Name:Abhijit Ghosh | Email:[email protected]
Id: 3 | Name:My Name | Email:[email protected]
Id: 5 | Name:Li Chao | Email:[email protected]
Id: 6 | Name:Tom Li | Email:[email protected]
Id: 24 | Name:Your Name | Email:[email protected]
 
Jul 26, 2012 5:41:32 PM org.hibernate.search.impl.SimpleIndexingProgressMonitor addToTotalCount
INFO: HSEARCH000027: Going to reindex 5 entities
Jul 26, 2012 5:41:32 PM org.hibernate.search.impl.SimpleIndexingProgressMonitor indexingCompleted
INFO: HSEARCH000028: Reindexed 5 entities
 
 
Enter search key (Toexittype'X')name
 
 
>>>>>>Record foundfor'name'
Id: 3 | Name:My Name | Email:[email protected]
Id: 24 | Name:Your Name | Email:[email protected]
 
 
Enter search key (Toexittype'X')Li
 
 
>>>>>>Record foundfor'Li'
Id: 5 | Name:Li Chao | Email:[email protected]
Id: 6 | Name:Tom Li | Email:[email protected]
 
 
Enter search key (Toexittype'X')test
 
 
>>>>>>Record foundfor'test'
 
 
Enter search key (Toexittype'X')x
End

 

Download Source Code

SrcCodes :  HibernateSearchHelloWorld.zip

 

你可能感兴趣的:(Hibernate Search is a full text search engine)