Indexes

JPA 2.1 introduces the @Index annotation. It lets you automatically create indexes on the database. Here is a sample for the Book entity:

@Table(name = "book",
indexes = {
@Index(name = "index_title", columnList = "title", unique = true),
@Index(name = "index_publisher", columnList = "publisher", unique = false) })
public class Book {
private String title;
private String publisher;...}

In your database, in the table book, you will see the two indexes called index_title and index_publisher tied respectively to the fields title and publisher of the Book entity. The unique field of the annotation indicates that the index enforces the constraint that you cannot have two equal values in that column in two different rows. Here are the indexes created in the database:

CREATE UNIQUE INDEX index_title ON book(title);
CREATE INDEX index_publisher ON book(publisher);

Another type of index is application side. An application server or any simple Java application can work with the database and decide to manage indexes on its own instead of on the database. The advantages are portability, decoupling, and scalability.

The decoupling because of the application is not dependent on the database so it can get more control over the indexes and choose the most appropriate configuration.

The application side indexes can be propagated in a cluster. It's a joke for a Java EE application server to manage the scalability of its components.

Lucene is the major open source index engine. Hibernate Search supports a set of annotation to manage the Lucene indexes. See now a sample of an entity indexed with Hibernate Search:

@Indexed(index = "indexes/topics") 
public class Topic implements Serializable, Comparable<Topic> {

@Id
private Integer id;
@IndexedEmbedded(includeEmbeddedObjecId = true, targetElement = Forum.class)
private Forum forum;

@Field(index = true)
private String subject;

private List<Post> posts;
...
}

The @Indexed annotation establishes the Topic class to be indexed. All indexes will be installed in the directory indexes | topics.

@IndexedEmbedded is very similar to the JPA @Embedded annotation. It specifies that an association is to be indexed in the root entity index. This allows queries involving associated objects properties. IncludeEmbeddedObjectId returns true if the ID of the embedded object should be included into the index, and false otherwise. targetElement overrides the target type of an association in case a collection overrides the type of the collection generics.

By default, the primary key marked as @Id is always . See a sample of Post entity too:

@Indexed(index = "indexes/posts")
public class Post implements Serializable {
@IndexedEmbedded(targetElement = Message.class)
@Embedded
private Message message;
...
}

And the embedded message:

@Embeddable
public class Message implements Serializable,Cloneable {
@Field(index=YES)
...
private String text = "";
...}

If you want a different indexed property from the primary key, you need to add the @Field annotation with index to YES so that it will be in the index repositories and it will be possible to search it.

See now how to execute a search through the indexes in Hibernate Search.

As the first thing, we need a search session called FullTextSession. It can be taken thanks to the current Entity Manager:

FullTextSession fullTextSession = getFullTextSession((Session) entityManager.getDelegate());

The getDelegate method of the Entity Manager returns the Hibernate session important to start the session of Hibernate search. Then we need a builder:

Builder builder = new Builder();

The builder builds the query programmatically. It can include more than a query, so it can elaborate them all together. See how to add the queries:

String[] fields = new String[]{"message.text","topic.subject"};
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields,new StandardAnalyzer());
builder.add(parser.parse("my_text"),MUST);

This query lets you search by a string keyword, in this case my_text. The text will be searched in the indexed fields message.text and topic.subject of the Topic entity seen before. Here another set of queries that will be added in AND. The MUST key implies that the set of queries will be executed in AND. Other options are:

  • SHOULD: The set of queries will be executed in OR
  • MUST_NOT: The negation of MUST
  • FILTER: As with MUST, except that these clauses do not participate in scoring:
builder.add(new TermQuery(new Term("topic.forum.id","0")),MUST); builder.add(new TermQuery(new Term("topic.forum.category.id","0")),MUST); 
builder.add(new WildcardQuery(new Term("poster.userId","*root")),MUST);

The first is a query by topic id = 0, the second by category id=0. The third by userId = "*root". The WildcardQuery is an extension of the TermQuery where you can search by wildcards. In our example the * lets you find all userId that end with root and not only the fixed key. Once we have configured the builder we can create our query:

FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(builder.build(),Post.class); fullTextQuery.setSort(getSort()); fullTextQuery.setProjection("topic.id");

And execute the results:

List topics = fullTextQuery.list();
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.137.162.110