最近在项目中使用 Spring 和 Hibernate 进行开发
![](/icons/84623dou.gif)
有感于 Criteria 比较好用
![](/icons/84623dou.gif)
在查询思路方法设计上可以灵活
![](/icons/84623de.gif)
根据 Criteria
![](/icons/84623de.gif)
特点来方便地进行查询条件
![](/icons/84623de.gif)
组装
![](/icons/84623dou2.gif)
现在对 Hibernate
![](/icons/84623de.gif)
Criteria
![](/icons/84623de.gif)
使用方法进行整理总结:
Hibernate 设计了 CriteriaSpec
![](/icons/84623if.gif)
ication 作为 Criteria
![](/icons/84623de.gif)
父接口
![](/icons/84623dou.gif)
下面提供了 Criteria和DetachedCriteria
![](/icons/84623dou2.gif)
Criteria 和 DetachedCriteria
![](/icons/84623de.gif)
主要区别在于创建
![](/icons/84623de.gif)
形式不
![](/icons/84623yi.gif)
样
![](/icons/84623dou.gif)
Criteria 是在线
![](/icons/84623de.gif)
![](/icons/84623dou.gif)
所以它是由 Hibernate Session 进行创建
![](/icons/84623de.gif)
;而 DetachedCriteria 是离线
![](/icons/84623de.gif)
![](/icons/84623dou.gif)
创建时无需Session
![](/icons/84623dou.gif)
DetachedCriteria 提供了 2 个静态思路方法 forClass(Class) 或 forEntityName(Name) 进行DetachedCriteria 例子
![](/icons/84623de.gif)
创建
![](/icons/84623dou2.gif)
Spring
![](/icons/84623de.gif)
框架提供了getHibernateTemplate
![](/icons/84623kh.gif)
.findByCriteria(detachedCriteria) 思路方法可以很方便地根据DetachedCriteria 来返回查询结果
![](/icons/84623dou2.gif)
Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件
![](/icons/84623dou2.gif)
可以设置 FetchMode( 联合查询抓取
![](/icons/84623de.gif)
模式 )
![](/icons/84623dou.gif)
设置排序方式
![](/icons/84623dou2.gif)
对于 Criteria 还可以设置 FlushModel(冲刷 Session
![](/icons/84623de.gif)
方式)和 LockMode (数据库锁模式)
![](/icons/84623dou2.gif)
下面对 Criterion 和 Projection 进行详细介绍说明
![](/icons/84623dou2.gif)
Criterion 是 Criteria
![](/icons/84623de.gif)
查询条件
![](/icons/84623dou2.gif)
Criteria 提供了 add(Criterion criterion) 思路方法来添加查询条件
![](/icons/84623dou2.gif)
Criterion 接口
![](/icons/84623de.gif)
主要实现包括: Example 、 Junction 和 SimpleExpression
![](/icons/84623dou2.gif)
而 Junction
![](/icons/84623de.gif)
实际使用是它
![](/icons/84623de.gif)
两个子类 conjunction 和 disjunction
![](/icons/84623dou.gif)
分别是使用 AND 和 OR 操作符进行来联结查询条件集合
![](/icons/84623dou2.gif)
Criterion
![](/icons/84623de.gif)
例子可以通过 Restrictions 工具类来创建
![](/icons/84623dou.gif)
Restrictions 提供了大量
![](/icons/84623de.gif)
静态思路方法
![](/icons/84623dou.gif)
如 eq (等于)、 ge (大于等于)、 between 等来思路方法
![](/icons/84623de.gif)
创建 Criterion 查询条件 (SimpleExpression 例子)
![](/icons/84623dou2.gif)
除此的外
![](/icons/84623dou.gif)
Restrictions 还提供了思路方法来创建 conjunction 和 disjunction 例子
![](/icons/84623dou.gif)
通过往该例子
![](/icons/84623de.gif)
add(Criteria) 思路方法来增加查询条件形成
![](/icons/84623yi.gif)
个查询条件集合
![](/icons/84623dou2.gif)
至于 Example
![](/icons/84623de.gif)
创建有所区别
![](/icons/84623dou.gif)
Example 本身提供了
![](/icons/84623yi.gif)
个静态思路方法 create(Object entity)
![](/icons/84623dou.gif)
即根据
![](/icons/84623yi.gif)
个对象(实际使用中
![](/icons/84623yi.gif)
般是映射到数据库
![](/icons/84623de.gif)
对象)来创建
![](/icons/84623dou2.gif)
然后可以设置
![](/icons/84623yi.gif)
些过滤条件:
Example exampleUser =Example.create(u)
.ignoreCase
![](/icons/84623kh.gif)
// 忽略大小写
.enableLike(MatchMode.ANYWHERE);
// 对 String 类型
![](/icons/84623de.gif)
属性
![](/icons/84623dou.gif)
无论在那里值在那里都匹配
![](/icons/84623dou2.gif)
相当于 %value% Project 主要是让 Criteria 能够进行报表查询
![](/icons/84623dou.gif)
并可以实现分组
![](/icons/84623dou2.gif)
Project 主要有 SimpleProjection 、ProjectionList 和 Property 3个实现
![](/icons/84623dou2.gif)
其中SimpleProjection 和 ProjectionList
![](/icons/84623de.gif)
例子化是由内建
![](/icons/84623de.gif)
Projections 来完成
![](/icons/84623dou.gif)
如提供
![](/icons/84623de.gif)
avg 、 count 、 max 、 min 、 sum 可以让开发者很容易对某个字段进行统计查询
![](/icons/84623dou2.gif)
Property 是对某个字段进行查询条件
![](/icons/84623de.gif)
设置
![](/icons/84623dou.gif)
如通过Porperty.forName(“color”).in(
![](/icons/84623new.gif)
String
![](/icons/84623zhk2.gif)
{“black”,”red”,”write”}); 则可以创建
![](/icons/84623yi.gif)
个 Project 例子
![](/icons/84623dou2.gif)
通过 criteria
![](/icons/84623de.gif)
add(Project) 思路方法加入到查询条件中去
![](/icons/84623dou2.gif)
使用 Criteria 进行查询
![](/icons/84623dou.gif)
主要要清晰
![](/icons/84623de.gif)
是 Hibernate 提供了那些类和思路方法来满足开发中查询条件
![](/icons/84623de.gif)
创建和组装
![](/icons/84623dou.gif)
下面介绍几种使用方法:
1. 创建
![](/icons/84623yi.gif)
个Criteria 例子
org.hibernate.Criteria接口表示特定持久类
![](/icons/84623de.gif)
![](/icons/84623yi.gif)
个查询
![](/icons/84623dou2.gif)
Session是 Criteria例子
![](/icons/84623de.gif)
工厂
![](/icons/84623dou2.gif)
Criteria crit = sess.createCriteria(Cat.
);
crit.
MaxResults(50);
List cats = crit.list
;
2. 限制结果集内容
![](/icons/84623yi.gif)
个单独
![](/icons/84623de.gif)
查询条件是org.hibernate.criterion.Criterion 接口
![](/icons/84623de.gif)
![](/icons/84623yi.gif)
个例子
![](/icons/84623dou2.gif)
org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型
![](/icons/84623de.gif)
工厂思路方法
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list
;
约束可以按逻辑分组
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.or(
Restrictions.eq( "age",
Integer(0) ),
Restrictions.isNull("age")
) )
.list
;
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.in( "name",
String
{ "Fritz", "Izi", "Pk" } ) )
.add( Restrictions.disjunction![](/icons/84623kh.gif)
.add( Restrictions.isNull("age") )
.add( Restrictions.eq("age",
Integer(0) ) )
.add( Restrictions.eq("age",
Integer(1) ) )
.add( Restrictions.eq("age",
Integer(2) ) )
) )
.list
;
Hibernate提供了相当多
![](/icons/84623de.gif)
内置criterion类型(Restrictions 子类), 但是尤其有用
![](/icons/84623de.gif)
是可以允许你直接使用SQL
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%",
Hibernate.STRING) )
.list
;
{alias}占位符应当被替换为被查询实体
![](/icons/84623de.gif)
列别名
![](/icons/84623dou2.gif)
Property例子是获得
![](/icons/84623yi.gif)
个条件
![](/icons/84623de.gif)
另外
![](/icons/84623yi.gif)
种途径
![](/icons/84623dou2.gif)
你可以通过
![](/icons/84623diaoyong.gif)
Property.forName
![](/icons/84623kh.gif)
创建
![](/icons/84623yi.gif)
个Property
![](/icons/84623dou2.gif)
Property age = Property.forName("age");
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.disjunction![](/icons/84623kh.gif)
.add( age.isNull
)
.add( age.eq(
Integer(0) ) )
.add( age.eq(
Integer(1) ) )
.add( age.eq(
Integer(2) ) )
) )
.add( Property.forName("name").in(
String
{ "Fritz", "Izi", "Pk" } ) )
.list
;
3. 结果集排序
你可以使用org.hibernate.criterion.Order来为查询结果排序
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.like("name", "F%")
.addOrder( Order.asc("name") )
.addOrder( Order.desc("age") )
.
MaxResults(50)
.list
;
List cats = sess.createCriteria(Cat.
)
.add( Property.forName("name").like("F%") )
.addOrder( Property.forName("name").asc
)
.addOrder( Property.forName("age").desc
)
.
MaxResults(50)
.list
;
4. 关联
你可以使用createCriteria
![](/icons/84623kh.gif)
非常容易
![](/icons/84623de.gif)
在互相关联
![](/icons/84623de.gif)
实体间建立 约束
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.like("name", "F%")
.createCriteria("kittens")
.add( Restrictions.like("name", "F%")
.list
;
注意第 2个 createCriteria
![](/icons/84623kh.gif)
返回
![](/icons/84623yi.gif)
个新
![](/icons/84623de.gif)
Criteria例子
![](/icons/84623dou.gif)
该例子引用kittens 集合中
![](/icons/84623de.gif)
元素
![](/icons/84623dou2.gif)
接下来
![](/icons/84623dou.gif)
替换形态在某些情况下也是很有用
![](/icons/84623de.gif)
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.createAlias("kittens", "kt")
.createAlias("mate", "mt")
.add( Restrictions.eqProperty("kt.name", "mt.name") )
.list
;
(createAlias
![](/icons/84623kh.gif)
并不创建
![](/icons/84623yi.gif)
个新
![](/icons/84623de.gif)
Criteria例子
![](/icons/84623dou2.gif)
)
Cat例子所保存
![](/icons/84623de.gif)
的前两次查询所返回
![](/icons/84623de.gif)
kittens集合是 没有被条件预过滤
![](/icons/84623de.gif)
![](/icons/84623dou2.gif)
如果你希望只获得符合条件
![](/icons/84623de.gif)
kittens
![](/icons/84623dou.gif)
你必须使用
![](/icons/84623return.gif)
Maps
![](/icons/84623kh.gif)
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.createCriteria("kittens", "kt")
.add( Restrictions.eq("name", "F%") )
.
Maps![](/icons/84623kh.gif)
.list
;
Iterator iter = cats.iterator
;
while ( iter.hasNext
) {
Map map = (Map) iter.next
;
Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);
Cat kitten = (Cat) map.get("kt");
}
5. 动态关联抓取
你可以使用
![](/icons/84623set.gif)
FetchMode
![](/icons/84623kh.gif)
在运行时定义动态关联抓取
![](/icons/84623de.gif)
语义
![](/icons/84623dou2.gif)
List cats = sess.createCriteria(Cat.
)
.add( Restrictions.like("name", "Fritz%") )
.
FetchMode("mate", FetchMode.EAGER)
.
FetchMode("kittens", FetchMode.EAGER)
.list
;
这个查询可以通过外连接抓取mate和kittens
![](/icons/84623dou2.gif)
6. 查询举例
org.hibernate.criterion.Example类允许你通过
![](/icons/84623yi.gif)
个给定例子 构建
![](/icons/84623yi.gif)
个条件查询
![](/icons/84623dou2.gif)
Cat cat =
Cat
;
cat.
Sex('F');
cat.
Color(Color.BLACK);
List results = session.createCriteria(Cat.
)
.add( Example.create(cat) )
.list
;
版本属性、标识符和关联被忽略
![](/icons/84623dou2.gif)
默认情况下值为null
![](/icons/84623de.gif)
属性将被排除
![](/icons/84623dou2.gif)
可以自行调整Example使的更实用
![](/icons/84623dou2.gif)
Example example = Example.create(cat)
.excludeZeroes
//exclude zero valued properties
.excludeProperty("color") //exclude the property named "color"
.ignoreCase
//perform
insensitive
comparisons
.enableLike
; //use like for
comparisons
List results = session.createCriteria(Cat.
)
.add(example)
.list
;
甚至可以使用examples在关联对象上放置条件
![](/icons/84623dou2.gif)
List results = session.createCriteria(Cat.
)
.add( Example.create(cat) )
.createCriteria("mate")
.add( Example.create( cat.getMate
) )
.list
;
7. 投影(Projections)、聚合(aggregation)和分组(grouping)
org.hibernate.criterion.Projections是 Projection
![](/icons/84623de.gif)
例子工厂
![](/icons/84623dou2.gif)
我们通过
![](/icons/84623set.gif)
Projection
![](/icons/84623kh.gif)
应用投影到
![](/icons/84623yi.gif)
个查询
![](/icons/84623dou2.gif)
List results = session.createCriteria(Cat.
)
.
Projection( Projections.rowCount
)
.add( Restrictions.eq("color", Color.BLACK) )
.list
;
List results = session.createCriteria(Cat.
)
.
Projection( Projections.projectionList![](/icons/84623kh.gif)
.add( Projections.rowCount
)
.add( Projections.avg("weight") )
.add( Projections.max("weight") )
.add( Projections.groupProperty("color") )
)
.list
;
在
![](/icons/84623yi.gif)
个条件查询中没有必要显式
![](/icons/84623de.gif)
使用 "group by"
![](/icons/84623dou2.gif)
某些投影类型就是被定义为 分组投影
![](/icons/84623dou.gif)
他们也出现在SQL
![](/icons/84623de.gif)
group by子句中
![](/icons/84623dou2.gif)
可以选择把
![](/icons/84623yi.gif)
个别名指派给
![](/icons/84623yi.gif)
个投影
![](/icons/84623dou.gif)
这样可以使投影值被约束或排序所引用
![](/icons/84623dou2.gif)
下面是两种区别
![](/icons/84623de.gif)
实现方式:
List results = session.createCriteria(Cat.
)
.
Projection( Projections.alias( Projections.groupProperty("color"), "colr" ) )
.addOrder( Order.asc("colr") )
.list
;
List results = session.createCriteria(Cat.
)
.
Projection( Projections.groupProperty("color").as("colr") )
.addOrder( Order.asc("colr") )
.list
;
alias
![](/icons/84623kh.gif)
和as
![](/icons/84623kh.gif)
思路方法简便
![](/icons/84623de.gif)
将
![](/icons/84623yi.gif)
个投影例子包装到另外
![](/icons/84623yi.gif)
个 别名
![](/icons/84623de.gif)
Projection例子中
![](/icons/84623dou2.gif)
简而言的
![](/icons/84623dou.gif)
当你添加
![](/icons/84623yi.gif)
个投影到
![](/icons/84623yi.gif)
个投影列表中时 你可以为它指定
![](/icons/84623yi.gif)
个别名:
List results = session.createCriteria(Cat.
)
.
Projection( Projections.projectionList![](/icons/84623kh.gif)
.add( Projections.rowCount
, "catCountByColor" )
.add( Projections.avg("weight"), "avgWeight" )
.add( Projections.max("weight"), "maxWeight" )
.add( Projections.groupProperty("color"), "color" )
)
.addOrder( Order.desc("catCountByColor") )
.addOrder( Order.desc("avgWeight") )
.list
;
List results = session.createCriteria(Domestic.
, "cat")
.createAlias("kittens", "kit")
.
Projection( Projections.projectionList![](/icons/84623kh.gif)
.add( Projections.property("cat.name"), "catName" )
.add( Projections.property("kit.name"), "kitName" )
)
.addOrder( Order.asc("catName") )
.addOrder( Order.asc("kitName") )
.list
;
也可以使用Property.forName
![](/icons/84623kh.gif)
来表示投影:
List results = session.createCriteria(Cat.
)
.
Projection( Property.forName("name") )
.add( Property.forName("color").eq(Color.BLACK) )
.list
;
List results = session.createCriteria(Cat.
)
.
Projection( Projections.projectionList![](/icons/84623kh.gif)
.add( Projections.rowCount
.as("catCountByColor") )
.add( Property.forName("weight").avg
.as("avgWeight") )
.add( Property.forName("weight").max
.as("maxWeight") )
.add( Property.forName("color").group
.as("color" )
)
.addOrder( Order.desc("catCountByColor") )
.addOrder( Order.desc("avgWeight") )
.list
;
8. 离线(detached)查询和子查询
DetachedCriteria类使你在
![](/icons/84623yi.gif)
个session范围的外创建
![](/icons/84623yi.gif)
个查询
![](/icons/84623dou.gif)
并且可以使用任意
![](/icons/84623de.gif)
Session来执行它
![](/icons/84623dou2.gif)
DetachedCriteria query = DetachedCriteria.forClass(Cat.
)
.add( Property.forName("sex").eq('F') );
//创建
个Session
Session session = .;
Transaction txn = session.beginTransaction
;
List results = query.getExecutableCriteria(session).
MaxResults(100).list
;
txn.commit
;
session.close
;
DetachedCriteria也可以用以表示子查询
![](/icons/84623dou2.gif)
条件例子包含子查询可以通过 Subqueries或者Property获得
![](/icons/84623dou2.gif)
DetachedCriteria avgWeight = DetachedCriteria.forClass(Cat.
)
.
Projection( Property.forName("weight").avg
);
session.createCriteria(Cat.
)
.add( Property.forName("weight).gt(avgWeight) )
.list
;
DetachedCriteria weights = DetachedCriteria.forClass(Cat.
)
.
Projection( Property.forName("weight") );
session.createCriteria(Cat.
)
.add( Subqueries.geAll("weight", weights) )
.list
;
相互关联
![](/icons/84623de.gif)
子查询也是有可能
![](/icons/84623de.gif)
:
DetachedCriteria avgWeightForSex = DetachedCriteria.forClass(Cat.
, "cat2")
.
Projection( Property.forName("weight").avg
)
.add( Property.forName("cat2.sex").eqProperty("cat.sex") );
session.createCriteria(Cat.
, "cat")
.add( Property.forName("weight).gt(avgWeightForSex) )
.list
;