专注于互联网--专注于架构

最新标签
网站地图
文章索引
Rss订阅

首页 »Java教程 » hibernate:Hibernate中Criteria的完整使用方法 »正文

hibernate:Hibernate中Criteria的完整使用方法

来源: 发布时间:星期五, 2009年1月23日 浏览:277次 评论:0
  最近在项目中使用 Spring 和 Hibernate 进行开发有感于 Criteria 比较好用在查询思路方法设计上可以灵活根据 Criteria 特点来方便地进行查询条件组装现在对 HibernateCriteria 使用方法进行整理总结:

  Hibernate 设计了 CriteriaSpecication 作为 Criteria 父接口下面提供了 Criteria和DetachedCriteria

  Criteria 和 DetachedCriteria 主要区别在于创建形式不 Criteria 是在线所以它是由 Hibernate Session 进行创建;而 DetachedCriteria 是离线创建时无需SessionDetachedCriteria 提供了 2 个静态思路方法 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 和 SimpleExpression 而 Junction 实际使用是它两个子类 conjunction 和 disjunction 分别是使用 AND 和 OR 操作符进行来联结查询条件集合

  Criterion 例子可以通过 Restrictions 工具类来创建Restrictions 提供了大量静态思路方法如 eq (等于)、 ge (大于等于)、 between 等来思路方法创建 Criterion 查询条件 (SimpleExpression 例子)除此的外 Restrictions 还提供了思路方法来创建 conjunction 和 disjunction 例子通过往该例子 add(Criteria) 思路方法来增加查询条件形成个查询条件集合

  至于 Example 创建有所区别 Example 本身提供了个静态思路方法 create(Object entity) 即根据个对象(实际使用中般是映射到数据库对象)来创建然后可以设置些过滤条件:

  Example exampleUser =Example.create(u)

  .ignoreCase // 忽略大小写

  .enableLike(MatchMode.ANYWHERE);

  // 对 String 类型属性无论在那里值在那里都匹配相当于 %value% Project 主要是让 Criteria 能够进行报表查询并可以实现分组 Project 主要有 SimpleProjection 、ProjectionList 和 Property 3个实现其中SimpleProjection 和 ProjectionList 例子化是由内建 Projections 来完成如提供 avg 、 count 、 max 、 min 、 sum 可以让开发者很容易对某个字段进行统计查询

  Property 是对某个字段进行查询条件设置如通过Porperty.forName(“color”).in( String{“black”,”red”,”write”}); 则可以创建个 Project 例子通过 criteria add(Project) 思路方法加入到查询条件中去

  使用 Criteria 进行查询主要要清晰是 Hibernate 提供了那些类和思路方法来满足开发中查询条件创建和组装下面介绍几种使用方法:

  1. 创建个Criteria 例子

  org.hibernate.Criteria接口表示特定持久类个查询Session是 Criteria例子工厂

Criteria crit = sess.createCriteria(Cat.);
crit.MaxResults(50);
List cats = crit.list;


  2. 限制结果集内容

  个单独查询条件是org.hibernate.criterion.Criterion 接口个例子

  org.hibernate.criterion.Restrictions类 定义了获得某些内置Criterion类型工厂思路方法List cats = sess.createCriteria(Cat.)
  .add( Restrictions.like("name", "Fritz%") )
  .add( Restrictions.between("weight", minWeight, maxWeight) )
  .list;


  约束可以按逻辑分组

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
    .add( Restrictions.isNull("age") )
    .add( Restrictions.eq("age", Integer(0) ) )
    .add( Restrictions.eq("age", Integer(1) ) )
    .add( Restrictions.eq("age", Integer(2) ) )
  ) )
  .list;


  Hibernate提供了相当多内置criterion类型(Restrictions 子类), 但是尤其有用是可以允许你直接使用SQL

List cats = sess.createCriteria(Cat.)
  .add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%",
Hibernate.STRING) )
  .list;


  {alias}占位符应当被替换为被查询实体列别名

  Property例子是获得个条件另外种途径你可以通过Property.forName 创建个Property

Property age = Property.forName("age");
List cats = sess.createCriteria(Cat.)
  .add( Restrictions.disjunction
    .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来为查询结果排序

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非常容易在互相关联实体间建立 约束

List cats = sess.createCriteria(Cat.)
  .add( Restrictions.like("name", "F%")
  .createCriteria("kittens")
    .add( Restrictions.like("name", "F%")
  .list;


  注意第 2个 createCriteria返回个新 Criteria例子该例子引用kittens 集合中元素 接下来替换形态在某些情况下也是很有用

List cats = sess.createCriteria(Cat.)
  .createAlias("kittens", "kt")
  .createAlias("mate", "mt")
  .add( Restrictions.eqProperty("kt.name", "mt.name") )
  .list;


  (createAlias并不创建个新 Criteria例子)

  Cat例子所保存的前两次查询所返回kittens集合是 没有被条件预过滤如果你希望只获得符合条件kittens 你必须使用Maps

List cats = sess.createCriteria(Cat.)
  .createCriteria("kittens", "kt")
  .add( Restrictions.eq("name", "F%") )
  .Maps
  .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. 动态关联抓取

  你可以使用FetchMode在运行时定义动态关联抓取语义

List cats = sess.createCriteria(Cat.)
  .add( Restrictions.like("name", "Fritz%") )
  .FetchMode("mate", FetchMode.EAGER)
  .FetchMode("kittens", FetchMode.EAGER)
  .list;


  这个查询可以通过外连接抓取mate和kittens

  6. 查询举例

  org.hibernate.criterion.Example类允许你通过个给定例子 构建个条件查询

Cat cat = Cat;
cat.Sex('F');
cat.Color(Color.BLACK);
List results = session.createCriteria(Cat.)
  .add( Example.create(cat) )
  .list;


  版本属性、标识符和关联被忽略默认情况下值为null属性将被排除

  可以自行调整Example使的更实用

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在关联对象上放置条件

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 例子工厂我们通过 Projection应用投影到个查询

List results = session.createCriteria(Cat.)
  .Projection( Projections.rowCount )
  .add( Restrictions.eq("color", Color.BLACK) )
  .list;
List results = session.createCriteria(Cat.)
  .Projection( Projections.projectionList
    .add( Projections.rowCount )
    .add( Projections.avg("weight") )
    .add( Projections.max("weight") )
    .add( Projections.groupProperty("color") )
  )
  .list;


  在个条件查询中没有必要显式使用 "group by" 某些投影类型就是被定义为 分组投影他们也出现在SQLgroup by子句中

  可以选择把个别名指派给个投影这样可以使投影值被约束或排序所引用下面是两种区别实现方式:

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和as思路方法简便个投影例子包装到另外个 别名Projection例子中简而言的当你添加个投影到个投影列表中时 你可以为它指定个别名:

List results = session.createCriteria(Cat.)
  .Projection( Projections.projectionList
    .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
    .add( Projections.property("cat.name"), "catName" )
    .add( Projections.property("kit.name"), "kitName" )
  )
  .addOrder( Order.asc("catName") )
  .addOrder( Order.asc("kitName") )
  .list;


  也可以使用Property.forName来表示投影:

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
    .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类使你在个session范围的外创建个查询并且可以使用任意 Session来执行它

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也可以用以表示子查询条件例子包含子查询可以通过 Subqueries或者Property获得



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;


  相互关联子查询也是有可能:

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;




0

相关文章

读者评论

发表评论

  • 昵称:
  • 内容: