2020-03-21

Hibernate Search - Mapping

Mapping

Let’s assume that your application contains the Hibernate ORM managed classes Book and Author and you want to index them in order to search the books contained in your database.

Book and Author entities BEFORE adding Hibernate Search specific annotations
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Book {

    @Id
    @GeneratedValue
    private Integer id;

    private String title;

    @ManyToMany
    private Set<Author> authors = new HashSet<>();

    public Book() {
    }

    // Getters and setters
    // ...

}
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

@Entity
public class Author {

    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @ManyToMany(mappedBy = "authors")
    private Set<Book> books = new HashSet<>();

    public Author() {
    }

    // Getters and setters
    // ...

}
To make these entities searchable, you will need to map them to an index structure. The mapping can be defined using annotations, or using a programmatic API; this getting started guide will show you a simple annotation mapping. For more details, refer to Mapping Hibernate ORM entities to indexes.

Below is an example of how the model above can be mapped.

Book and Author entities AFTER adding Hibernate Search specific annotations
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.GenericField;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.Indexed;
import org.hibernate.search.mapper.pojo.mapping.definition.annotation.IndexedEmbedded;

@Entity
@Indexed 
public class Book {

    @Id 
    @GeneratedValue
    private Integer id;

    @GenericField 
    private String title;

    @ManyToMany
    @IndexedEmbedded 
    private Set<Author> authors = new HashSet<>();

    public Book() {
    }

    // Getters and setters
    // ...

}
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;

import org.hibernate.search.mapper.pojo.mapping.definition.annotation.GenericField;

@Entity 
public class Author {

    @Id
    @GeneratedValue
    private Integer id;

    @GenericField 
    private String name;

    @ManyToMany(mappedBy = "authors")
    private Set<Book> books = new HashSet<>();

    public Author() {
    }

    // Getters and setters
    // ...

}
@Indexed marks Book as indexed, i.e. an index will be created for that entity, and that index will be kept up to date.
By default, the JPA @Id is used to generate a document identifier.
@GenericField maps a property to an index field with the same name and type. As such, the field is indexed in a way that only allows exact matches; full-text matches will be discussed in a moment.
@IndexedEmbedded allows to "embed" the indexed form of associated objects (entities or embeddables) into the indexed form of the embedding entity. Here, the Author class defines a single indexed field, name. Thus adding @IndexedEmbedded to the authors property of Book will add a single authors.name field to the Book index. This field will be populated automatically based on the content of the authors property, and the books will be reindexed automatically whenever the name property of their author changes. See Mapping associated elements with @IndexedEmbedded for more information.
Entities that are only @IndexedEmbedded in other entities, but do not require to be searchable by themselves, do not need to be annotated with @Indexed.
This is a very simple example, but is enough to get started. Just remember that Hibernate Search allows more complex mappings:

Other @*Field annotations exist, some of them allowing full-text search, some of them allowing finer-grained configuration for field of a certain type. You can find out more about @*Field annotations in Mapping a property to an index field with @GenericField, @FullTextField, …​.

Properties, or even types, can be mapped with finer-grained control using "bridges". See Bridges for more information.

No comments:

Post a Comment