QBC查询就是经过使用Hibernate提供的Query By Criteria API来查询对象,这种API封装了SQL语句的动态拼装,对查询提供了更加面向对象的功能接口。咱们看下面的示例程序: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以及全部面向对象编程语言的编程方式,因此大多数的持久层框架都提供了对这种方式查询的支持。下面咱们讲 解这种查询方式的各个技术细节。express
一、Criteria查询表达式: 编程
正如咱们所见,Expression对查询语句的表达式进行了封装和限制,下表列出了Expression全部的方法,以及每一个方法所对应的查询表达式及其限制。session
方法描述
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”表达式
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表达式
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),并非数据库表中的实际字段名称,而是实体对象中映射实际数据表字段的类属性名称。
二、示例查询: 编程语言
示例查询是经过Example类来完成的,Example类实现了Criterion接口,能够用做Criteria查询条件,Example类的做用是:根据已有对象,查询属性值与之相同的其余对象。以下代码所示:hibernate
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 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语句:code
select * from user where name=’zx’;
在上面的代码中exampleuser称为示例对象。
在Hibernate中队示例查询,默认状况下会排除掉示例对象中属性值为 空的属性,还能够调用Example.excludeNone(排除空串值)/excludeZeros(排除零值),或者调用 Example.excludeProperty方法来指定排除特定属性。对象
示例查询主要应用于组合查询中,好比根据用户输入的查询条件动态生成最终的查询语句,经过使用示例查询,能够避免因为查询条件过多而写的大量if判断语句。
三、复合查询:
复合查询主要是处理,具备关联关系的两个实体怎样进行关联查询,好比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 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对象),来构造复合查询,在数据库一端是经过内链接查询来实现。
四、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;
五、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);