Hibernate Search integration with Hibernate Criteria Part II
In a previous entry we were talking about how we implemented Lucene searches using Hibernate Search. In this post we’ll talk about how and why we integrated Hibernate Search with Hibernate Criteria.
Apparently Hibernate Search offered lucene sort and pagination features, so our first approach was to substitute MySQL with Lucene for all queries coming from the user search forms.
We had lots of search fields, some of them were exact matches, others range queries, and likes as well, so each one should be indexed differently. Exact and range fields shouldn’t be analyzed, meanwhile some of the likes should depending on the like query.
So, we map all the fields and start making some easy queries. Apparently they were going fine, and pagination was also fine, but sorting wasn’t. Some columns weren’t ordering results as they should, and it was due to the analyzer, which removed some tokens from the fields and caused the sorting to fail, so we had to map each analyzed field twice (analyzed for the searches and not analyzed for the sorting).
Also, we saw that since our hibernate mappings were not bidirectional, any change in every association of the root entity wouldn’t be reflected in the lucene index (because hibernate wouldn’t know which entities are related to the association). Making all the associations bidirectional was not straight-forward and would affect most of the entities CRUD operations, besides other problems like JAXB complaining about cycles,…
So at the end, we prefered to use lucene only for full text queries and use MySQL for filtering other fields, pagination and sorting.
Basically, we did the same Hibernate Search is doing internally, which is getting the document’s ids from the Lucene Index and performing a MySQL query to get the results, with the difference that we are filtering/paginating/sorting results in the second query instead of on the first.
FullTextSession session = Search.getFullTextSession(getSession());
QueryBuilder queryBuilder = session.getSearchFactory().buildQueryBuilder().forEntity(clazz).get();
Query luceneQuery = queryBuilder....createQuery();
FullTextQuery fullTextQuery = session.createFullTextQuery(luceneQuery, classe);
List<clazz> objectList = fullTextQuery.list();