Working Example on Github
There’s a small, self contained mavenised example project over on Github to accompany this post – check it out here: https://github.com/adrianmilne/jpa-lucene-spring-demo
Running the Demo
See the README file over on GitHub for details of running the demo. Essentially – it’s just running the Unit Tests, with the usual maven build and test results output to the console – example below. This is the result of running the DBUnit test, which inserts Book data into the HSQL database using JPA, and then uses Lucene to query the data, testing that the expected Books are returned (i.e. only those int he SCI-FI category, containing the word ‘Space’, and ensuring that any with ‘Space’ in the title appear before those with ‘Space’ only in the description.
The Book Entity
Our simple example stores Books. The Book entity class below is a standard JPA Entity with a few additional annotations to identify it to Lucene:
@Indexed – this identifies that the class will be added to the Lucene index. You can define a specific index by adding the ‘index’ attribute to the annotation. We’re just choosing the simplest, minimal configuration for this example.
In addition to this – you also need to specify which properties on the entity are to be indexed, and how they are to be indexed. For our example we are again going for the default option by just adding an @Field annotation with no extra parameters. We are adding one other annotation to the ‘title’ field – @Boost – this is just telling Lucene to give more weight to search term matches that appear in this field (than the same term appearing in the description field).
This example is purposefully kept minimal in terms of the ins-and-outs of Lucene (I may cover that in a later post) – we’re really just concentrating on the integration with JPA and Spring for now.
The Book Manager
The BookManager class acts as a simple service layer for the Book operations – used for adding books and searching books. As you can see, the JPA database resources are autowired in by Spring from the application-context.xml. We are just using an in-memory hsql database in this example.
This is the Spring configuration file. You can see in the JPA Entity Manager configuration the key for ‘hibernate.search.default.indexBase’ is added to the jpaPropertyMap to tell Lucene where to create the index. We have also externalised the database login credentials to a properties file (as you may wish to change these for different environments), for example by updating the propertyConfigurer to look for and use a different external properties if it finds one on the file system).
Testing Using DBUnit
In the project is an example of using DBUnit with Spring to test adding and searching against the database using DBUnit to populate the database with test data, exercise the Book Manager search operations and then clean the database down. This is a great way to test database functionality and can be easily integrated into maven and continuous build environments.
Because DBUnit bypasses the standard JPA insertion calls – the data does not get automatically added to the Lucene index. We have a method exposed on the service interface to update the Full Text index ‘updateFullTextIndex()’ – calling this causes Lucene to update the index with the current data in the database. This can be useful when you are adding search to pre-populated databases to index the existing content.
The source data for the test is defined in an xml file