前几天看到Hibernate与Lucene的整合框架Hiberate Search3.0.0.GA版出来了,昨天试这写了一个Demo,感觉用起来的确很方便的,贴出来与大家分享一下。
1、创建POJO
package
com.yehui;
import
javax.persistence.CascadeType;
import
javax.persistence.Column;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.GenerationType;
import
javax.persistence.Id;
import
javax.persistence.JoinColumn;
import
javax.persistence.ManyToOne;
import
javax.persistence.Table;
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.IndexedEmbedded;
import
org.hibernate.search.annotations.Store;
/**
* Employee generated by MyEclipse Persistence Tools
*/
@Entity
@Table(name
=
"
employee
"
, catalog
=
"
hise
"
, uniqueConstraints
=
{}
)
@Indexed(index
=
"
indexes/employee
"
)
public
class
Employee
implements
java.io.Serializable
{
private
static
final
long
serialVersionUID
=
7794235365739814541L
;
private
Integer empId;
private
String empName;
private
Department dept;
private
String empNo;
private
Double empSalary;
//
Constructors
/**
default constructor
*/
public
Employee()
{
}
/**
minimal constructor
*/
public
Employee(Integer empId)
{
this
.empId
=
empId;
}
/**
full constructor
*/
public
Employee(Integer empId, String empName,
String empNo, Double empSalary)
{
this
.empId
=
empId;
this
.empName
=
empName;
this
.empNo
=
empNo;
this
.empSalary
=
empSalary;
}
//
Property accessors
@Id
@GeneratedValue(strategy
=
GenerationType.AUTO)
@Column(name
=
"
emp_id
"
, unique
=
true
, nullable
=
false
, insertable
=
true
, updatable
=
true
)
@DocumentId
public
Integer getEmpId()
{
return
this
.empId;
}
public
void
setEmpId(Integer empId)
{
this
.empId
=
empId;
}
@Column(name
=
"
emp_name
"
, unique
=
false
, nullable
=
true
, insertable
=
true
, updatable
=
true
, length
=
30
)
@Field(name
=
"
name
"
, index
=
Index.TOKENIZED, store
=
Store.YES)
public
String getEmpName()
{
return
this
.empName;
}
public
void
setEmpName(String empName)
{
this
.empName
=
empName;
}
@Column(name
=
"
emp_no
"
, unique
=
false
, nullable
=
true
, insertable
=
true
, updatable
=
true
, length
=
30
)
@Field(index
=
Index.UN_TOKENIZED)
public
String getEmpNo()
{
return
this
.empNo;
}
public
void
setEmpNo(String empNo)
{
this
.empNo
=
empNo;
}
@Column(name
=
"
emp_salary
"
, unique
=
false
, nullable
=
true
, insertable
=
true
, updatable
=
true
, precision
=
7
)
public
Double getEmpSalary()
{
return
this
.empSalary;
}
public
void
setEmpSalary(Double empSalary)
{
this
.empSalary
=
empSalary;
}
@ManyToOne(cascade
=
CascadeType.ALL)
@JoinColumn(name
=
"
dept_id
"
)
@IndexedEmbedded(prefix
=
"
dept_
"
, depth
=
1
)
public
Department getDept()
{
return
dept;
}
public
void
setDept(Department dept)
{
this
.dept
=
dept;
}
}
package
com.yehui;
import
java.util.List;
import
javax.persistence.Column;
import
javax.persistence.Entity;
import
javax.persistence.GeneratedValue;
import
javax.persistence.GenerationType;
import
javax.persistence.Id;
import
javax.persistence.OneToMany;
import
javax.persistence.Table;
import
org.hibernate.search.annotations.ContainedIn;
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.Store;
/**
* Department generated by MyEclipse Persistence Tools
*/
@Entity
@Table(name
=
"
department
"
, catalog
=
"
hise
"
, uniqueConstraints
=
{}
)
@Indexed(index
=
"
indexes/department
"
)
public
class
Department
implements
java.io.Serializable
{
private
static
final
long
serialVersionUID
=
7891065193118612907L
;
private
Integer deptId;
private
String deptNo;
private
String deptName;
private
List
<
Employee
>
empList;
//
Constructors
@OneToMany(mappedBy
=
"
dept
"
)
@ContainedIn
public
List
<
Employee
>
getEmpList()
{
return
empList;
}
public
void
setEmpList(List
<
Employee
>
empList)
{
this
.empList
=
empList;
}
/**
default constructor
*/
public
Department()
{
}
/**
minimal constructor
*/
public
Department(Integer deptId)
{
this
.deptId
=
deptId;
}
/**
full constructor
*/
public
Department(Integer deptId, String deptNo, String deptName)
{
this
.deptId
=
deptId;
this
.deptNo
=
deptNo;
this
.deptName
=
deptName;
}
//
Property accessors
@Id
@GeneratedValue(strategy
=
GenerationType.AUTO)
@Column(name
=
"
dept_id
"
, unique
=
true
, nullable
=
false
, insertable
=
true
, updatable
=
true
)
@DocumentId
public
Integer getDeptId()
{
return
this
.deptId;
}
public
void
setDeptId(Integer deptId)
{
this
.deptId
=
deptId;
}
@Column(name
=
"
dept_no
"
, unique
=
false
, nullable
=
true
, insertable
=
true
, updatable
=
true
, length
=
30
)
public
String getDeptNo()
{
return
this
.deptNo;
}
public
void
setDeptNo(String deptNo)
{
this
.deptNo
=
deptNo;
}
@Column(name
=
"
dept_name
"
, unique
=
false
, nullable
=
true
, insertable
=
true
, updatable
=
true
, length
=
30
)
@Field(name
=
"
name
"
, index
=
Index.TOKENIZED,store
=
Store.YES)
public
String getDeptName()
{
return
this
.deptName;
}
public
void
setDeptName(String deptName)
{
this
.deptName
=
deptName;
}
}
不了解Hibernate映射相关的Annotation的朋友可以到Hibernate的官方网站下载Hibernate Annotation Reference,有http://wiki.redsaga.com/翻译的中文文档。当然,也可以直接使用hbm.xml文件。
Hibernate Search相关的Annotation主要有两个:
@Indexed 标识需要进行索引的对象,
属性 index 指定索引文件的路径
@Field 标注在类的get属性上,标识一个索引的Field
属性 index 指定是否索引,与Lucene相同
store 指定是否索引,与Lucene相同
name 指定Field的name,默认为类属性的名称
analyzer 指定分析器
另外@IndexedEmbedded 与 @ContainedIn 用于关联类之间的索引
@IndexedEmbedded有两个属性,一个prefix指定关联的前缀,一个depth指定关联的深度
如上面两个类中Department类可以通过部门名称name来索引部门,在Employee与部门关联的前缀为dept_,因此可以通过部门名称dept_name来索引一个部门里的所有员工。
2、配置文件
<?
xml version='1.0' encoding='UTF-8'
?>
<!
DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"
>
<
hibernate-configuration
>
<
session-factory
>
<
property
name
="hibernate.dialect"
>
org.hibernate.dialect.MySQLDialect
</
property
>
<
property
name
="hibernate.connection.url"
>
jdbc:mysql://localhost:3306/hise
</
property
>
<
property
name
="hibernate.connection.username"
>
root
</
property
>
<
property
name
="hibernate.connection.password"
>
123456
</
property
>
<
property
name
="hibernate.connection.driver_class"
>
com.mysql.jdbc.Driver
</
property
>
<
property
name
="hibernate.search.default.directory_provider"
>
org.hibernate.search.store.FSDirectoryProvider
</
property
>
<
property
name
="hibernate.search.default.indexBase"
>
e:/index
</
property
>
<
mapping
class
="com.yehui.Employee"
/>
<
mapping
class
="com.yehui.Department"
/>
</
session-factory
>
</
hibernate-configuration
>
如果使用JPA,配置文件为
<?
xml version="1.0" encoding="UTF-8"
?>
<
persistence
xmlns
="http://java.sun.com/xml/ns/persistence"
xmlns:xsi
="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation
="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version
="1.0"
>
<
persistence-unit
name
="jpaPU"
transaction-type
="RESOURCE_LOCAL"
>
<
provider
>
org.hibernate.ejb.HibernatePersistence
</
provider
>
<
class
>
com.yehui.Department
</
class
>
<
class
>
com.yehui.Employee
</
class
>
<
properties
>
<
property
name
="hibernate.connection.driver_class"
value
="com.mysql.jdbc.Driver"
/>
<
property
name
="hibernate.connection.url"
value
="jdbc:mysql://localhost:3306/hise"
/>
<
property
name
="hibernate.connection.username"
value
="root"
/>
<
property
name
="hibernate.connection.password"
value
="123456"
/>
<
property
name
="hibernate.search.default.directory_provider"
value
="org.hibernate.search.store.FSDirectoryProvider"
/>
<
property
name
="hibernate.search.default.indexBase"
value
="e:/index"
/>
</
properties
>
</
persistence-unit
>
</
persistence
>
主要就是添加两个属性,
hibernate.search.default.directory_provider指定Directory的代理,即把索引的文件保存在硬盘中(
org.hibernate.search.store.FSDirectoryProvider)还是内存里(
org.hibernate.search.store.RAMDirectoryProvider),保存在硬盘的话
hibernate.search.default.indexBase属性指定索引保存的路径。
3、测试代码
package
com.yehui;
import
static
junit.framework.Assert.assertNotNull;
import
static
junit.framework.Assert.assertTrue;
import
java.util.List;
import
org.apache.lucene.analysis.StopAnalyzer;
import
org.apache.lucene.queryParser.QueryParser;
import
org.hibernate.Query;
import
org.hibernate.Session;
import
org.hibernate.SessionFactory;
import
org.hibernate.Transaction;
import
org.hibernate.cfg.AnnotationConfiguration;
import
org.hibernate.search.FullTextSession;
import
org.hibernate.search.Search;
import
org.junit.After;
import
org.junit.Before;
import
org.junit.BeforeClass;
import
org.junit.Test;
public
class
SearchResultsHibernate
{
private
static
SessionFactory sf
=
null
;
private
static
Session session
=
null
;
private
static
Transaction tx
=
null
;
@BeforeClass
public
static
void
setupBeforeClass()
throws
Exception
{
sf
=
new
AnnotationConfiguration().configure(
"
hibernate.cfg.xml
"
).buildSessionFactory();
assertNotNull(sf);
}
@Before
public
void
setUp()
throws
Exception
{
session
=
sf.openSession();
tx
=
session.beginTransaction();
tx.begin();
}
@After
public
void
tearDown()
throws
Exception
{
tx.commit();
session.close();
}
public
static
void
tearDownAfterClass()
throws
Exception
{
if
(sf
!=
null
)
sf.close();
}
@Test
public
void
testAddDept()
throws
Exception
{
Department dept
=
new
Department();
dept.setDeptName(
"
Market
"
);
dept.setDeptNo(
"
6000
"
);
Employee emp
=
new
Employee();
emp.setDept(dept);
emp.setEmpName(
"
Kevin
"
);
emp.setEmpNo(
"
KGP1213
"
);
emp.setEmpSalary(8000d);
session.save(emp);
}
@Test
public
void
testFindAll()
throws
Exception
{
Query query
=
session.createQuery(
"
from Department
"
);
List
<
Department
>
deptList
=
query.list();
assertTrue(deptList.size()
>
0
);
}
@Test
public
void
testIndex()
throws
Exception
{
FullTextSession fullTextSession
=
Search.createFullTextSession(session);
assertNotNull(session);
QueryParser parser
=
new
QueryParser(
"
name
"
,
new
StopAnalyzer());
org.apache.lucene.search.Query luceneQuery
=
parser
.parse(
"
name:Kevin
"
);
Query hibQuery
=
fullTextSession.createFullTextQuery(luceneQuery,
Employee.
class
);
List list
=
hibQuery.list();
assertTrue(list.size()
>
0
);
}
@Test
public
void
testIndex2()
throws
Exception
{
FullTextSession fullTextSession
=
Search.createFullTextSession(session);
assertNotNull(session);
QueryParser parser
=
new
QueryParser(
"
dept_name
"
,
new
StopAnalyzer());
org.apache.lucene.search.Query luceneQuery
=
parser
.parse(
"
dept_name:Market
"
);
Query hibQuery
=
fullTextSession.createFullTextQuery(luceneQuery,
Employee.
class
);
List list
=
hibQuery.list();
assertTrue(list.size()
>
0
);
}
}
测试通过。OK
1、创建POJO







































































































































































































Hibernate Search相关的Annotation主要有两个:
@Indexed 标识需要进行索引的对象,
属性 index 指定索引文件的路径
@Field 标注在类的get属性上,标识一个索引的Field
属性 index 指定是否索引,与Lucene相同
store 指定是否索引,与Lucene相同
name 指定Field的name,默认为类属性的名称
analyzer 指定分析器
另外@IndexedEmbedded 与 @ContainedIn 用于关联类之间的索引
@IndexedEmbedded有两个属性,一个prefix指定关联的前缀,一个depth指定关联的深度
如上面两个类中Department类可以通过部门名称name来索引部门,在Employee与部门关联的前缀为dept_,因此可以通过部门名称dept_name来索引一个部门里的所有员工。
2、配置文件
























































3、测试代码








































































































