Criteria特性

 QBC查询:
 QBC查询就是通过使用Hibernate提供的Query By Criteria API来查询对象,这种API封装了SQL语句的动
态拼装,对查询提供了更加面向对象的功能接口。我们看下面的示例程序:
            Criteria criteria=session.createCriteria(User.class);
            criteria.add(Expression.eq(“name”,”zx”));
            criteria.add(Expression.eq(“age”,new Integer(27));
            List list=criteria.list();
            当执行criteria.list()时会生成类似这样的SQL语句:
Select * from user where name=’zx’ and age=27;所以在这里我们可以看出,Criteria实际上是一个
查询容器,它对查询条件表达式的添加进行了封装,具体的查询条件是通过add()方法添加的,而且具体的查
询条件的表达式运算是通过Expression指定的。Hibernate在运行期会根据Criteria指定的表达式条件来
添加查询条件,并且生成查询语句。这种方式非常符合Java以及所有面向对象编程语言的编程方式,所以大多
数的持久层框架都提供了对这种方式查询的支持。下面我们讲解这种查询方式的各个技术细节。
            1、Criteria查询表达式:
            正如我们所见,Expression对查询语句的表达式进行了封装和限制,下表列出了Expression
所有的方法,以及每个方法所对应的查询表达式及其限制。
            方法  描述
            Expression.eq   
            对应SQL的“field=value”表达式
            如:Expression.eq(“name”,”zx”);
            Expression.allEq    方法的参数为一个Map类型对象,包含多个名/值对对应关系,相当于
多个Expression.eq的叠加
            Expression.gt   对应SQL的“field>value”表达式
            Expression.ge   对应SQL的“field>=value”表达式
            Expression.lt   对应SQL的“field<value”表达式
            Expression.le   对应SQL的“field<=value”表达式
            Expression.between  对应SQL语句的between表达式,如:查询年龄在21与27岁之间的用户,
可以写成Expression.between(“age”,new Integer(21),new Integer(27));
            Expression.like     对应SQL语句的”field like value”表达式
            Expression.in   对应SQL语句的“field in(……)”表达式
            Expression.eqProperty   用于比较两个属性值,对应”field=field”SQL表达式
            Expression.gtProperty   用于比较两个属性值,对应”field>field”SQL表达式
            Expression.geProperty   用于比较两个属性值,对应”field>=field”SQL表达式
            Expression.ltProperty   用于比较两个属性值,对应”field<field”SQL表达式
            Expression.leProperty   用于比较两个属性值,对应”field<=field”SQL表达式
            Expression.and  对应SQL语句的And关系组合,
如:Expression.and(Expression.eq(“name”,”zx”),Expression.eq(“sex”,”1”));
            Expression.or   对应SQL语句的Or关系组合,
如:Expression.or(Expression.eq(“name”,”zx”),Expression.eq(“name”,”zhaoxin”));
            Expression.sql  作为补充这个方法提供了原生SQL语句查询的支持,在执行时直接通过原生SQL
语句进行限定,
如:Expression.sql(“lower({alias}.name) like (?)”,“zhao%”,Hibernate.STRING) ;在运行时
{ alias }将会由当前查询所关联的实体类名替换,()中的?将会由”zhao%”替换,
并且类型由Hibernate.STRING指定。
            
注意:Expression各方法中的属性参数(各方法中的第一个参数)所指定的属性名称(如:name,sex),
并不是数据库表中的实际字段名称,而是实体对象中映射实际数据表字段的类属性名称。
             
            2、示例查询:
               示例查询是通过Example类来完成的,Example类实现了Criterion接口,
可以用作Criteria查询条件,Example类的作用是:根据已有对象,
查询属性值与之相同的其他对象。如下代码所示:
            Criteria criteria=session.createCriteria(User.class);
            User exampleuser=new User(“zx”);
            criteria.add(Example.create(exampleuser));
            List list=criteria.list();
            for(int i=0;i<list.size();i++){
               User user=(User)list.get(i);
               System.out.println(user.getName()+”\n”);
            }
            上述代码中User exampleuser=new User(“zx”);criteria.add(Example.create(exampleuser));两句相当于
            criteria.add(Expression.eq(“name”,”zx”));因此会生成类似如下的SQL语句:
            select * from user where name=’zx’;在上面的代码中exampleuser称为示例对象。
              在Hibernate中队示例查询,默认情况下会排除掉示例对象中属性值为空的属性,
还可以调用Example.excludeNone(排除空串值)/excludeZeros
(排除零值),
或者调用Example.excludeProperty方法来指定排除特定属性。
               示例查询主要应用于组合查询中,
比如根据用户输入的查询条件动态生成最终的查询语句,
通过使用示例查询,
可以避免由于查询条件过多而写的大量if判断语句。
            3、复合查询:
            复合查询主要是处理,具有关联关系的两个实体怎样进行关联查询,
比如User实体对象与Addres实体对象具有一对多的关联关系,
我们可以如下构造符合查询:
            Criteria criteria=session.createCriteria(User.class);
               Criteria addcriteria=criteria.createCriteria(“addresses”);(1)
               addcriteria.add(Express.like(“address”,”%tianjin%”));
              List list=criteria.list();
               for(int i=0;i<list.size();i++){
                 User user=(User)list.get(i);
                 System.out.println(user.getName()+”\n”);
                 Set addresses=user.getAddresses();
                 Iterator it=addresses.iterator();
                 while(it.hasNext(){
                  Address address=(Address)it.next();
                  System.out.println(address.getAddress()+”\n”);
                 }
               }
            当执行到了(1)处时,
表明要针对User对象的addresses属性添加新的查询条件,
因此当执行criteria.list()时,
Hibernate会生成类似如下的SQL语句:
Select * from user inner join address on user.id=address.id where address.address like
 ‘%shanghai%’;
正如我们所见,
我们可以通过向Criteria中添加保存关联对象的集合属性
(addresses属性保存与User对象相关联的Address对象),
来构造复合查询,
在数据库一端是通过内连接查询来实现。
             
             
             
            4、Criteria的高级特性:
            A、限定返回记录条数:
            
 我们可以通过利用Criteria.setFirstResult/setMaxResult方法来限定返回某一次查询的记录数,
如下代码:
            Criteria criteria=session.createCriteria(User.class);
            criteria.setFirstResult(100);
            criteria.setMaxResult(200);
            通过以上代码可以设定该次查询返回user表中的从第100条记录开始直到第200条记录结束的100条记录。
            B、对查询结果进行排序:
             可通过使用net.sf.hibernate.expression.Order类可以对查询结果集进行排序,如下面代码:
            Criteria criteria=session.createCriteria(User.class);
            criteria.add(Expression.eq(“groupid”,”2”);
            criteria.addOrder(Order.asc(“name”));
            criteria.addOrder(Order.desc(“groupid”));
            List list=criteria.list();
            通过使用Order类的asc()/desc()方法,
可以指定针对某个字段的排序逻辑,
如果执行上述代码,会生成类似如下的SQL语句:
Select * from user where groupid=’2’ order by name asc,groupid desc
            C、分组与统计:
               在Hibernate3中,对Criteria又增添了新功能,
可以支持分组与统计功能,
在Hibernate3中增加了Projections以及ProjectionList类,
这两个类对分组与统计功能进行了封装,
如下代码:
            Criteria criteria=session.createCriteria(User.class);
            criteria.setProjection(Projections.groupProperty(“age”));(1)
            List list=criteria.list();
            Iterator it=list.iterator();
            while(it.hasNext()){
             System.out.println(it.next());
            }
            通过(1)处的代码,
我们通过Projections类指定了用于分组的目标属性,当进行检索时Hibernate会生成类似如下的SQL语句:
            Select age from user group by age;
            还可以通过使用Projections的avg()/rowCount()/count()/max()/min()/countDistinct()等方法来实现统计功能,如下面的代码示例:
            Criteria criteria=session.createCriteria(User.class);
            criteria.setProjection(Projections.avg(“age”));(1)
            List list=criteria.list();
            Iterator it=list.iterator();
            while(it.hasNext()){
             System.out.println(it.next());
            }
            通过(1)处的代码,我们实现了对用户平均年龄的统计,当进行检索时,Hibernate会生成类似如下的SQL语句:
            Select avg(age) from user;
            另外,在SQL语句中的多条件分组与统计功能,可以利用ProjectionList类来实现,如下面代码所示:
            Criteria criteria=session.createCriteria(User.class);
            ProjectionList prolist=Projections.projectionList();
            prolist.add(Projections.groupProperty(“age”));
            prolist.add(Projections.rowCount());
            criteria.setProjection(prolist);
            List list=criteria.list();
            通过以上代码,实现了对不同年龄人员数量的分组统计,当进行检索时,Hibernate会生成类似如下的SQL语句:
            Select age,count(*) from user group by age;
            5、DetachedCriteria:
            在Hibernate2中,
Criteria实例是与创建它的Session实例具有相同的生命周期的,
也就是说,Session实例是它所创建的Criteria实例的宿主,
当Session关闭时,寄生于Session实例的Criteria都将失效。
这就对Criteria的重用造成了困难,
为了实现Criteria实例的重用,
在Hibernate3中提供了一个DetachedCriteria类,
DetachedCriteria实例的生命周期与Session实例的生命周期无关
,我们可以利用DetachedCriteria对
一些常用的Criteria查询条件进行抽离,
当需要进行检索时再与Session实例关联,
从而获得运行期的Criteria实例。
如下面的代码所示:
  DetachedCriteria dc= DetachedCriteria.forClass(User.class);
  dc.add(Expression.eq(“name”,”zhaoxin”));
 dc.add(Expression.eq(“sex”,”1”));
 Criteria criteria=dc.getExecutableCriteria(session);
 Iterator it=criteria.list().iterator();
 while(it.hasNext()){
 User user=(User)it.next();
 System.out.println(user.getName());
}
 正如我们所见,DetachedCriteria的生存周期与session实例无关,
当需要进行检索时,通过getExecutableCriteria(session)方法,
与当前的Session实例关联并获得运行期的Criteria实例,
完成检索。
            DetachedCriteria也可以用于完成子查询功能,
如下代码所示:
DetachedCriteria dc= DetachedCriteria.forClass(User.class);
            dc.setProjection(Projections.avg(“age”));
            Criteria criteria=session.createCriteria(User.class);
            criteria.add(Subqueries.propertyGt(“age”,dc));
            List list=criteria.list();
            通过Subqueries类,实现了添加子查询的功能,
我们将DetachedCriteria所设定的查询条件,
当作子查询添加到了运行时Criteria实例的查询条件中,
当执行检索时Hibernate会生成类似如下的SQL语句:
Select * from user where age>(select avg(age) from user group by age);
             

Hibernate除了处理查询结果集中的对象之外,
还可以将结果集中的结果当做行和列集来使用,
这与通过JDBC执行select查询获得的数据的使用方式相似。
因此,Hibernate也支持属性、统计函数和Group By等查询。

            要想使用Hibernate的投影统计功能,
首先要从org.hibernate.criterion.Projections工厂类获得org.hibernate.criterion.Projection对象。与Restrictions类相似,Projections类提供了几个用来获取Projection实例的静态工厂方法。
在获得Projection对象之后,
使用setProjection()方法将它添加到Criteria对象中。
注意,返回的结果集是Object类型,
需要对结果进行适当的类型转换。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容