Hibernate Searchは、アノテーションによってドメインモデルの索引を生成し、テキストのクエリーからドメインモデルのエンティティを取得することができるようにしたプロダクトです。Hibernate Searchは、検索エンジンにApache Luceneを使っています。Hibernate Searchもこのたび晴れてHibernateのTOPプロジェクトに昇格したプロダクトです。(まだベータ版ですが)
ということでHibernate Validatorを触ったり、Hibernate Shardsを触ったりしたついでに少しだけ触ってみます。Hello Worldレベルです。
- 必要なライブラリ
- lucene-core-2.1.0.jar
- hibernate-search.jar
- エンティティクラス
- 定義ファイル
- エンティティを登録してみる
- 検索してみる
面倒なので、前回のHibernate Validatorを使ったときのものを流用することにします。これに加えて必要なものは
です。どちらもHibernate Searchのアーカイブの中に含まれています。JMSを使うのであればjms.jarも要りますが今回は使いません。なおLuceneが2.1.0よりも古いと動かなくなったみたいなので注意です。
前回のHibernate Validatorを使ったときのエンティティを少しだけ改造します。
@Entity
@Indexed
public class Customer implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@DocumentId
public int id;
@NotNull
@Length(max = 10)
@Field(index = Index.TOKENIZED, store = Store.YES)
public String name;
@Range(min = 0, max = 100)
public int age;
public String email;
@Past
public Date birthday;
}
赤字のところしか変えていません。
hibernate.cfg.xmlはこんな感じです。Hibernate Search用に変えている部分は省略しています。
<hibernate-configuration>
<session-factory>
・・・
<property name="hibernate.search.default.directory_provider">
org.hibernate.search.store.FSDirectoryProvider
</property>
<property name="hibernate.search.default.indexBase">C:\Indexes</property>
<mapping package="net.grandnature.example.entity"/>
<mapping class="net.grandnature.example.invoice.entity.Customer"/>
<event type="post-update">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
<event type="post-insert">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
<event type="post-delete">
<listener class="org.hibernate.search.event.FullTextIndexEventListener"/>
</event>
</session-factory>
</hibernate-configuration>
Luceneによって生成されるインデックスのファイル達がC:\Indexesに保存される設定です。
Sessionをそのまま使うのではなくFullTextSessionを取得してそれを使うようにします。それ以外は普通です。
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
FullTextSession fullTextSession = Search.createFullTextSession(session);
Transaction tx = fullTextSession.beginTransaction();
Customer customer = new Customer();
customer.name = "KIDA Taro";
customer.age = 76;
customer.email = "kida@example.com";
DateFormat parser = DateFormat.getDateInstance();
ex.birthday = parser.parse("1930/12/06");
fullTextSession.save(ex);
tx.commit();
fullTextSession.close();
これを実行してエンティティがRDBに永続化されると、Luceneのインデックスも同時に生成されています。C:\Indexesの中にそれらしいファイルが出来ていると思いますが、それらがLuceneのインデックスファイルです。
SessionFactory sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
FullTextSession fullTextSession = Search.createFullTextSession(session);
BooleanQuery booleanQuery = new BooleanQuery();
booleanQuery.add(new PrefixQuery(new Term("name", "Kida")),BooleanClause.Occur.SHOULD);
Query fullTextQuery = fullTextSession.createFullTextQuery(booleanQuery);
Iterator result = fullTextQuery.iterate();
while (result.hasNext()) {
Customer customer = (Customer) result.next();
System.out.printf("%d - %s%n", customer.id, customer.name);
}
・・・
BooleanQuery、PrefixQuery、BooleanClause、TermはLuceneのクラスです。QueryはHibernateのQueryです。こんな感じでクエリーから該当するHibernateのエンティティのインスタンスを取得できます。