Hibernate Search是在apache Lucene的基础上建立的主要用于Hibernate的持久化模型的全文检索工具。像Lucene这样的检索引擎能够给我们的项目在进行检索的时候带来非常高的效率,但是它们在基本对象的检索时会有一些问题,比如不能实现检索内容跟实体的转换,Hibernate Search正是在这样的情况下发展起来的,基于对象的检索引擎,能够很方便的将检索出来的内容转换为具体的实体对象。此外Hibernate Search能够根据需要进行同步或异步的索引更新。
下面是一些比较基本的用法(我用的是基于spring的)
先要在ApplicationContext里面的hibernate配置里面进行配置,下面是sessionFactory的配置:
如果单独使用的话也是要配置那些属性的:
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan">
<list>
<value>com.tiantian.test.model</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">
org.hibernate.dialect.MySQL5InnoDBDialect
</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<!-- hibernate search -->
<prop key="hibernate.search.default.directory_provider">filesystem</prop>
<prop key="hibernate.search.default.indexBase">var/lucene/indexes</prop><!--索引的存放位置-->
</props>
</property>
</bean>
需要进行检索的实体类:
import java.util.Date; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.search.annotations.DateBridge; import org.hibernate.search.annotations.DocumentId; import org.hibernate.search.annotations.Field; import org.hibernate.search.annotations.Index; import org.hibernate.search.annotations.Indexed; import org.hibernate.search.annotations.Resolution; @Entity @Table(name = "t_Model4") @Indexed//这个一定要加,表示该类将被Hibernate Search纳入检索范围 public class Model4 { private int id; private String name; private String address; private Date date = new Date(); @Id @GeneratedValue @DocumentId//对于GeneratedValue可以不用这个注解,表示文档的id public int getId() { return id; } public void setId(int id) { this.id = id; } @Field(index = Index.TOKENIZED)//需要索引的属性,index表示分词策略 public String getName() { return name; } public void setName(String name) { this.name = name; } @Field(index = Index.TOKENIZED) public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Field(index = Index.TOKENIZED) //索引date时需要传入一个date对象 @DateBridge(resolution = Resolution.DAY)//时间属性中需要索引的具体属性,可以是年、月、日、小时等 public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String toString() { return " id = " + id + ", \r\n name = " + name + ", \r\n address = " + address + ", \r\n date = " + date; }
下面是一段检索的示例代码:(匹配检索)
@SuppressWarnings("unchecked") @Override//Pager是我自定义的一个分页工具类 public Pager<Model4> find(String key, int offset, int maxResults) { // TODO Auto-generated method stub //第一步,获得Hibernate的Session对象 Session session = this.getHibernateTemplate().getSessionFactory().getCurrentSession(); //第二步,通过Hibernate的Session获取FullTextSession对象 FullTextSession fullTextSession = Search.getFullTextSession(session); //获取特定类的特定QueryBuilder对象 QueryBuilder queryBuilder = fullTextSession.getSearchFactory().buildQueryBuilder().forEntity(Model4.class).get(); //得到search query org.apache.lucene.search.Query query = queryBuilder.keyword().onField("name").andField("address").matching(key).createQuery();//key表示要用于检索的词 //这里使用FullTextQuery和org.hibernate.Query来分装org.apache.lucene.search.Query都是可以的, //但FullTextQuery的功能比org.hibernate.Query的功能要强大一点,究竟什么时候要用org.hibernate.Query而不能用 //org.apache.lucene.search.Query这个我暂时还没有发现! FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery(query, Model4.class); Sort sort = new Sort(new SortField("id",SortField.INT));//后一个参数表示排序字段的类型 fullTextQuery.setSort(sort);//排序依据 fullTextQuery.setFirstResult(offset).setMaxResults(maxResults);//很显然的分页操作 int totalResults = fullTextQuery.getResultSize();//获取满足条件的总记录数 List<Model4> data = fullTextQuery.list(); Pager<Model4> pager = new Pager<Model4>(); pager.setData(data); pager.setTotalResults(totalResults); return pager; }
范围检索的示例代码(主要用于日期或者数字型字段):
/** * range,范围检索,主要用于数字和日期等 */ @SuppressWarnings("unchecked") @Override public Pager<Model7> find(int offset, int maxResults) { // TODO Auto-generated method stub Session session = this.getHibernateTemplate().getSessionFactory() .getCurrentSession(); FullTextSession fullTextSession = Search.getFullTextSession(session); QueryBuilder queryBuilder = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity(Model7.class).get(); Query query = queryBuilder.range().onField("num").above(30) .createQuery();//表示30以上 FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( query, Model7.class); int totalResults = fullTextQuery.getResultSize(); List<Model7> data = fullTextQuery.setFirstResult(offset) .setMaxResults(maxResults).list(); Pager<Model7> pager = new Pager<Model7>(); pager.setData(data); pager.setTotalResults(totalResults); return pager; }
除什么之外的记录的示例代码:
@SuppressWarnings("unchecked") @Override /** * except除了什么之外的所有的记录 */ public Pager<Model7> findExcept(String key, int offset, int maxResults) { // TODO Auto-generated method stub Session session = this.getHibernateTemplate().getSessionFactory() .getCurrentSession(); FullTextSession fullTextSession = Search.getFullTextSession(session); QueryBuilder queryBuilder = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity(Model7.class).get(); // except方法用于指定需要排除的查询 Query query = queryBuilder .all() .except(queryBuilder.keyword().onField("address").matching(key) .createQuery()).createQuery(); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( query, Model7.class); int totalResults = fullTextQuery.getResultSize(); List<Model7> data = fullTextQuery.setFirstResult(offset) .setMaxResults(maxResults).list(); Pager<Model7> pager = new Pager<Model7>(); pager.setData(data); pager.setTotalResults(totalResults); return pager; }
(必须有或必须没有的内容)的示例代码:
/** * 哪些必须有,哪些必须没有,哪些可有可无 */ public Pager<Model7> findShouldMust(String nameShould, String addressMust, int offset, int maxResults) { // TODO Auto-generated method stub Session session = this.getHibernateTemplate().getSessionFactory() .getCurrentSession(); FullTextSession fullTextSession = Search.getFullTextSession(session); QueryBuilder queryBuilder = fullTextSession.getSearchFactory() .buildQueryBuilder().forEntity(Model7.class).get(); // should表示可有可无,must表示必须有,mustnot表示必须没有 Query query = queryBuilder .bool() .should(queryBuilder.keyword().onField("name") .matching(nameShould).createQuery()) .must(queryBuilder.keyword().onField("address") .matching(addressMust).createQuery()).createQuery(); FullTextQuery fullTextQuery = fullTextSession.createFullTextQuery( query, Model7.class); int totalResults = fullTextQuery.getResultSize(); List<Model7> data = fullTextQuery.setFirstResult(offset) .setMaxResults(maxResults).list(); Pager<Model7> pager = new Pager<Model7>(); pager.setData(data); pager.setTotalResults(totalResults); return pager; }
关于Hibernate Search的更多操作可以查阅其官方文档 HTML (single page)