最近在项目中使用 Spring 和 Hibernate 进行开发有感于 Criteria 比较好用在查询方法设计上可以灵活的根据 Criteria 的特点来方便地进行查询条件的组装现在对 Hibernate的Criteria的用法进行总结
Hibernate 设计了 CriteriaSpecification 作为 Criteria 的父接口下面提供了 Criteria和DetachedCriteria
Criteria 和 DetachedCriteria 的主要区别在于创建的形式不一样 Criteria 是在线的所以它是由 Hibernate Session 进行创建的而 DetachedCriteria 是离线的创建时无需SessionDetachedCriteria 提供了 个静态方法 forClass(Class) 或 forEntityName(Name)进行DetachedCriteria 实例的创建 Spring 的框架提供了getHibernateTemplate()findByCriteria(detachedCriteria) 方法可以很方便地根据DetachedCriteria 来返回查询结果
Criteria 和 DetachedCriteria 均可使用 Criterion 和 Projection 设置查询条件可以设置 FetchMode( 联合查询抓取的模式 ) 设置排序方式对于 Criteria 还可以设置 FlushModel(沖刷 Session 的方式)和 LockMode (数据库锁模式)
下面对 Criterion 和 Projection 进行详细说明
Criterion 是 Criteria 的查询条件Criteria 提供了 add(Criterion criterion) 方法来添加查询条件
Criterion 接口的主要实现包括 Example Junction 和 Simpl********** 而Junction 的实际使用是它的两个子类 conjunction 和 disjunction 分别是使用 AND 和 OR 操作符进行来联结查询条件集合
Criterion 的实例可以通过 Restrictions 工具类来创建Restrictions 提供了大量的静态方法如 eq (等于) ge (大于等于) between 等来方法的创建 Criterion 查询条件(Simpl********** 实例)除此之外 Restrictions 还提供了方法来创建 conjunction 和disjunction 实例通过往该实例的 add(Criteria) 方法来增加查询条件形成一个查询条件集合
至于 Example 的创建有所不同 Example 本身提供了一个静态方法 create(Objectentity) 即根据一个对象(实际使用中一般是映射到数据库的对象)来创建然后可以设置一些过滤条件
Example exampleUser =Examplecreate(u)
ignoreCase() // 忽略大小写
enableLike(MatchModeANYWHERE);
Project 主要是让 Criteria 能够进行报表查询并可以实现分组 Project 主要有SimpleProjection ProjectionList 和 Property 三个实现其中SimpleProjection 和ProjectionList 的实例化是由内建的 Projections 来完成如提供的 avg count max min sum 可以让开发者很容易对某个字段进行统计查询
Property 是对某个字段进行查询条件的设置如通过PorpertyforName(color)in(new String[]{blackredwrite}); 则可以创建一个 Project 实例通过criteria 的 add(Project) 方法加入到查询条件中去
使用 Criteria 进行查询主要要清晰的是 Hibernate 提供了那些类和方法来满足开发中查询条件的创建和组装下面介绍几种用法
创建一个Criteria 实例
orghibernateCriteria接口表示特定持久类的一个查询Session是 Criteria实例的工厂
Criteria crit = sesscreateCriteria(Catclass);
critsetMaxResults();
List cats = critlist();
限制结果集内容
一个单独的查询条件是orghibernatecriterionCriterion 接口的一个实例
orghibernatecriterionRestrictions类 定义了获得某些内置Criterion类型的工厂方法
List cats = sesscreateCriteria(Catclass)
add( Restrictionslike(name Fritz%) )
add( Restrictionsbetween(weight minWeight maxWeight) )
list();
约束可以按逻辑分组
orghibernatecriterionRestrictions类 定义了获得某些内置Criterion类型的工厂方法
List cats = sesscreateCriteria(Catclass)
add( Restrictionslike(name Fritz%) )
add( Restrictionsbetween(weight minWeight maxWeight) )
list();
Hibernate提供了相当多的内置criterion类型(Restrictions 子类) 但是尤其有用的是可以允许你直接使用SQL
List cats = sesscreateCriteria(Catclass)
add( Restrictionssql(lower({alias}name) like lower(?) Fritz%
HibernateSTRING) )
list();
{alias}占位符应当被替换为被查询实体的列别名
Property实例是获得一个条件的另外一种途径你可以通过调用PropertyforName() 创建一个Property
Property age = PropertyforName(age);
List cats = sesscreateCriteria(Catclass)
add( Restrictionsdisjunction()
add( ageisNull() )
add( ageeq( new Integer() ) )
add( ageeq( new Integer() ) )
add( ageeq( new Integer() ) )
) )
add( PropertyforName(name)in( new String[] { Fritz Izi Pk } ) )
list();
结果集排序
你可以使用orghibernatecriterionOrder来为查询结果排序
List cats = sesscreateCriteria(Catclass)
add( Restrictionslike(name F%)
addOrder( Orderasc(name) )
addOrder( Orderdesc(age) )
setMaxResults()
list();
List cats = sesscreateCriteria(Catclass)
add( PropertyforName(name)like(F%) )
addOrder( PropertyforName(name)asc() )
addOrder( PropertyforName(age)desc() )
setMaxResults()
list();
关联
你可以使用createCriteria()非常容易的在互相关联的实体间建立约束
List cats = sesscreateCriteria(Catclass)
add( Restrictionslike(name F%)
createCriteria(kittens)
add( Restrictionslike(name F%)
list();
注意第二个 createCriteria()返回一个新的 Criteria实例该实例引用kittens 集合中的元素接下来替换形态在某些情况下也是很有用的
List cats = sesscreateCriteria(Catclass)
createAlias(kittens kt)
createAlias(mate mt)
add( RestrictionseqProperty(ktname mtname) )
list();
(createAlias()并不创建一个新的 Criteria实例)
Cat实例所保存的之前两次查询所返回的kittens集合是 没有被条件预过滤的如果你希望只获得符合条件的kittens 你必须使用returnMaps()
List cats = sesscreateCriteria(Catclass)
createCriteria(kittens kt)
add( Restrictionseq(name F%) )
returnMaps()
list();
Iterator iter = erator();
while ( iterhasNext() ) {
Map map = (Map) iternext();
Cat cat = (Cat) mapget(CriteriaROOT_ALIAS);
Cat kitten = (Cat) mapget(kt);
}
动态关联抓取
你可以使用setFetchMode()在运行时定义动态关联抓取的语义
List cats = sesscreateCriteria(Catclass)
add( Restrictionslike(name Fritz%) )
setFetchMode(mate FetchModeEAGER)
setFetchMode(kittens FetchModeEAGER)
list();
这个查询可以通过外连接抓取mate和kittens
查询示例
orghibernatecriterionExample类允许你通过一个给定实例 构建一个条件查询
Cat cat = new Cat();
catsetSex(F);
catsetColor(ColorBLACK);
List results = sessioncreateCriteria(Catclass)
add( Examplecreate(cat) )
list();
版本属性标识符和关联被忽略默认情况下值为null的属性将被排除可以自行调整Example使之更实用
Example example = Examplecreate(cat)
excludeZeroes() //exclude zero valued properties
excludeProperty(color) //exclude the property named color
ignoreCase() //perform case insensitive string comparisons
enableLike(); //use like for string comparisons
List results = sessioncreateCriteria(Catclass)
add(example)
list();
甚至可以使用examples在关联对象上放置条件
List results = sessioncreateCriteria(Catclass)
add( Examplecreate(cat) )
createCriteria(mate)
add( Examplecreate( catgetMate() ) )
list();
投影(Projections)聚合(aggregation)和分组(grouping)
orghibernatecriterionProjections是 Projection 的实例工厂我们通过调用setProjection()应用投影到一个查询
List results = sessioncreateCriteria(Catclass)
setProjection( ProjectionsrowCount() )
add( Restrictionseq(color ColorBLACK) )
list();
List results = sessioncreateCriteria(Catclass)
setProjection( ProjectionsprojectionList()
add( ProjectionsrowCount() )
add( Projectionsavg(weight) )
add( Projectionsmax(weight) )
add( ProjectionsgroupProperty(color) )
)
list();
在一个条件查询中没有必要显式的使用 group by 某些投影类型就是被定义为 分组投影他们也出现在SQL的group by子句中
可以选择把一个别名指派给一个投影这样可以使投影值被约束或排序所引用下面是两种不同的实现方式
List results = sessioncreateCriteria(Catclass)
setProjection( Projectionsalias( ProjectionsgroupProperty(color) colr ) )
addOrder( Orderasc(colr) )
list();
List results = sessioncreateCriteria(Catclass)
setProjection( ProjectionsgroupProperty(color)as(colr) )
addOrder( Orderasc(colr) )
list();
alias()和as()方法简便的将一个投影实例包装到另外一个 别名的Projection实例中简而言之当你添加一个投影到一个投影列表中时 你可以为它指定一个别名
List results = sessioncreateCriteria(Catclass)
setProjection( ProjectionsprojectionList()
add( ProjectionsrowCount() catCountByColor )
add( Projectionsavg(weight) avgWeight )
add( Projectionsmax(weight) maxWeight )
add( ProjectionsgroupProperty(color) color )
)
addOrder( Orderdesc(catCountByColor) )
addOrder( Orderdesc(avgWeight) )
list();
List results = sessioncreateCriteria(Domesticclass cat)
createAlias(kittens kit)
setProjection( ProjectionsprojectionList()
add( Projectionsproperty(catname) catName )
add( Projectionsproperty(kitname) kitName )
)
addOrder( Orderasc(catName) )
addOrder( Orderasc(kitName) )
list();
也可以使用PropertyforName()来表示投影
List results = sessioncreateCriteria(Catclass)
setProjection( PropertyforName(name) )
add( PropertyforName(color)eq(ColorBLACK) )
list();
List results = sessioncreateCriteria(Catclass)
setProjection( ProjectionsprojectionList()
add( ProjectionsrowCount()as(catCountByColor) )
add( PropertyforName(weight)avg()as(avgWeight) )
add( PropertyforName(weight)max()as(maxWeight) )
add( PropertyforName(color)group()as(color )
)
addOrder( Orderdesc(catCountByColor) )
addOrder( Orderdesc(avgWeight) )
list();
离线(detached)查询和子查询
DetachedCriteria类使你在一个session范围之外创建一个查询并且可以使用任意的 Session来执行它
DetachedCriteria query = DetachedCriteriaforClass(Catclass)
add( PropertyforName(sex)eq(F) );
//创建一个Session
Session session = ;
Transaction txn = sessionbeginTransaction();
List results = querygetExecutableCriteria(session)setMaxResults()list();
mit();
sessionclose();
DetachedCriteria也可以用以表示子查询条件实例包含子查询可以通过 Subqueries或者Property获得
DetachedCriteria avgWeight = DetachedCriteriaforClass(Catclass)
setProjection( PropertyforName(weight)avg() );
sessioncreateCriteria(Catclass)
add( PropertyforName(weight)gt(avgWeight) )
list();
DetachedCriteria weights = DetachedCriteriaforClass(Catclass)
setProjection( PropertyforName(weight) );
sessioncreateCriteria(Catclass)
add( SubqueriesgeAll(weight
相互关联的子查询也是有可能的
DetachedCriteria avgWeightForSex = DetachedCriteriaforClass(Catclass cat)
setProjection( PropertyforName(weight)avg() )
add( PropertyforName(catsex)eqProperty(catsex) );
sessioncreateCriteria(Catclass cat)
add( PropertyforName(