public class Product {
private Long id;
private String name;
private String description;
}
Is there any way to implement a full text search with JpaRepository for the description of the class Product ?
A full-text index in MySQL is an index of type FULLTEXT . Full-text indexes can be used only with InnoDB or MyISAM tables, and can be created only for CHAR , VARCHAR , or TEXT columns.
The @Query annotation takes precedence over named queries, which are annotated with @NamedQuery or defined in an orm.xml file. It's a good approach to place a query definition just above the method inside the repository rather than inside our domain model as named queries.
You can use Hibernate Search, a library that plugs into Hibernate ORM to index your entities into a Lucene index on the filesystem, on the fly, when you send them to your database. See the Getting started guide.
(EDIT: Nowadays Hibernate Search also supports using Elasticsearch as a backend; it will automatically duplicate part of your database in Elasticsearch OR in a local Lucene index, whichever you chose.)
Querying the Lucene/Elasticsearch index is a bit different than querying the database, so you cannot use HQL or Criteria like you usually would. Hibernate Search offers its own query DSL.
If you want to use auto-magically generated method implementations in your repository, you can rely on Snowdrop, which is a Hibernate Search / Spring Data integration, but it hasn't been updated in a while.
Your best bet is probably to define query methods in your repository interface, then implement them yourself using Hibernate Search APIs. It's really not that complicated, and it's generally recommended for all but the most obvious queries. See the Spring Data JPA documentation.
Essentially you'll have something like the snippet below. Remember that you will need to reindex your database before this works! See the getting started guide for more information.
With Hibernate Search 6+:
@Indexed // Add this
public class Product {
private Long id;
@FullTextField // And this
private String name;
@FullTextField // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
return Search.session(em).search(Product.class)
.where(f -> f.match()
.fields("name", "description")
.matching(terms))
.fetchHits(offset, limit);
}
}
OR with Hibernate Search 5:
@Indexed // Add this
public class Product {
private Long id;
@Field // And this
private String name;
@Field // And this
private String description;
}
public interface ProductRepository extends CrudRepository<Product, Long>, CustomizedProductRepository {
// Declare automatically generated methods here
}
public interface CustomizedProductRepository {
List<Product> search(String terms, int limit, int offset);
}
public class CustomizedProductRepositoryImpl implements CustomizedProductRepository {
@PersistenceContext
private EntityManager em;
@Override
public List<Product> search(String terms, int limit, int offset) {
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(em);
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory()
.buildQueryBuilder().forEntity(Product.class).get();
org.apache.lucene.search.Query luceneQuery = queryBuilder
.keyword()
.onFields("name", "description")
.matching(terms)
.createQuery();
// wrap Lucene query in a javax.persistence.Query
javax.persistence.Query jpaQuery =
fullTextEntityManager.createFullTextQuery(luceneQuery, Product.class);
jpaQuery.setMaxResults(limit);
jpaQuery.setFirstResult(offset);
// execute search
return jpaQuery.getResultList();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With