Hibernate(三)Criteria查询

来源:互联网 发布:人文社会科学类软件 编辑:程序博客网 时间:2024/06/01 08:48
Criteria查询是与HQL查询、原生sql查询完全不一样的查询形式,是一种对象查询。Hibernate提供了Criteria接口、Criterion接口和Restrictions类、Order类等API,用于运行时动态生成查询语句,使用起来非常简便,并且支持连缀写法。
1.条件查询

(1)使用Criteria查询需要以下步骤:
      ①使用Session接口的createCriteria()方法创建Criteria对象
      ②使用Restrictions类提供的静态方法设置查询条件,这些方法返回一个Criterion对象,表示一个查询条件,Criteria接口提供了add()方法
           来添加查询条件
      ③使用Criteria接口的list()方法执行查询

(2)下面来演示最基本的用法,没有添加任何查询条件:
public static void main(String[] args) {Session session=HibernateUtil.currentSession();Transaction tx=session.beginTransaction();//创建Criteria对象Criteria criteria=session.createCriteria(Dept.class);List<Dept> list=criteria.list();for (Dept dept : list) {System.out.println(dept.getDeptName()+"\t"+dept.getDeptNo());}tx.commit();HibernateUtil.closeSession();}
(3)查询位置在“NEW YORK”的Dept信息:
//创建Criteria对象Criteria criteria=session.createCriteria(Dept.class);//添加查询条件,一个Criterion对象就是一个查询条件,这里的location是实体类中的属性名Criterion criterion=Restrictions.eq("location", "NEW YORK");criteria.add(criterion);List<Dept> list=criteria.list();for (Dept dept : list) {System.out.println(dept.getDeptName()+"\t"+dept.getDeptNo());}
(4)Hibernate提供了Restrictions类来添加查询条件,主要的方法如下:

①Criteria的比较运算SimpleExpression Restrictions.eq(String propertyName,Object value)等于SimpleExpression Restrictions.ne(String propertyName,Object value)不等于SimpleExpression Restrictions.gt(String propertyName,Object value)大于SimpleExpression Restrictions.ge(String propertyName,Object value)大于等于SimpleExpression Restrictions.lt(String propertyName,Object value)小于SimpleExpression Restrictions.le(String propertyName,Object value)小于等于Criterion Restrictions.isNull(String propertyName)等于空值Criterion Restrictions.isNotNull(String propertyName)非空值

②Criteria的范围运算

Criterion Restrictions.in(String property,Collection values)

Criterion Restrictions.in(String property,Object[] values)

等于列表

中的某一

个值


Criterion Restrictions.not(

Restrictions.in()

)

不等于列

表中任意一个值

Criterion Restrictions.between(String property,Object lo,Object hi)

大于等于值1并

且小于等于值2

Criterion  Restrictions.not(

Restrictions.between()

)

小于值1或者大于

值2

③Criteria支持的字符串模式匹配

SimpleExpression Restrictions.like(String property,Object value)

SimpleExpression Restrictions.like(String property,Objectvalue,MatchMode matchMode)

字符串模式匹配

Criterion Restrictions.ilike(String property,Object value)

Criterion Restrictions.ilike(String property,Objectvalue,MatchMode matchMode)

字符串模式匹配,同

忽略大小写时

注意:字符串匹配可以用MatchMode的静态常量来确定匹配的位置
④Criteria的逻辑运算LogicalExpression  Restrictions.and(Criterion c1,Criterion c2)逻辑与

LogicalExpression  Restrictions.or(Criterion c1,Criterion c2)

或者

Disjunction Restrictions.disjunction()

逻辑或

LogicalExpression  Restrictions.not(Criterion expression)

逻辑非

⑤Criteria的集合运算Criterion Restrictions.isEmpty(String propertyName)集合为空,不包含任何元素Criterion Restrictions.isNotEmpty(String propertyName)集合不为空

2.排序
Hibernate提供了org.hibernate.criterion.Order类来对查询结果进行排序,在为Criteria对象添加排序条件的时候要使用addOrder()方法,而不再是add()方法
如:查询员工工资小于3000的员工并按照降序排序:
/** * 1.criteria的add()方法返回的都是自身对象,所以可以通过连缀调用的方式继续添加条件; * 2.注意:如果实体类中的工资属性是double型的,这里的3000后要加D(或d),否则会抛出 * 不能将Integer转换成Double类型的异常 */List<Emp> list=session.createCriteria(Emp.class).add(Restrictions.lt("sal", 3000D)).addOrder(Order.desc("sal")).list();for (Emp emp : list) {System.out.println(emp.getSal());}
3.分页
Criteria的分页同HQL的分页用法一致,都是通过setFirstResult()和setMaxResults()方法来实现的,
uniqueResult()的用法一致,我在《Hibernate学习(二)HQL&SQL参数绑定、投影和分页以及命名查询》中已进行解释,这里就不再过多赘述。
4.连接查询
Criteria查询和HQL都支持连接查询,但是Criteria只支持内连接和迫切左外连接查询。Criteria提供了createCriteria()createAlias()方法来建立内连接。
例如:查询部门名称为“ACCOUNTING”并且名字中包含“l”的员工集合
①使用createCriteria()方式
/** * 1.为了防止属性的命名冲突,在使用时尽量加上别名,如“e”和“d”; * 2.其中的dept是Emp实体类中拥有的属性,Emp和Dept是多对一的关系 */List<Emp> list=session.createCriteria(Emp.class,"e").add(Restrictions.ilike("e.empName", "l",MatchMode.ANYWHERE)).createCriteria("dept", "d").add(Restrictions.eq("d.deptName", "ACCOUNTING")).list();for (Emp emp : list) {System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());}
②使用createAlias()方式
List<Emp> list=session.createCriteria(Emp.class,"e").add(Restrictions.ilike("e.empName", "l",MatchMode.ANYWHERE)).createAlias("dept", "d").add(Restrictions.eq("d.deptName", "ACCOUNTING")).list();for (Emp emp : list) {System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());}
两种方式的使用效果是一样的,输出结果:
CLARK ACCOUNTING
MILLER ACCOUNTING

5.投影
      Hibernate提供了Projection接口和Projections类来支持Criteria查询的投影。Projections类是用来构建Projection对象的工厂类,通过调用Criteria接口的setProjection()方法来设置投影属性
(1)查询单个属性时
       如,查询部门的deptName属性
/** * 1.setProjection()方法设置投影属性 * 2.Property类实现了Projection接口,forName()方法制定了投影属性的名称,并返回Property对象 */List<String> list=session.createCriteria(Dept.class).setProjection(Property.forName("deptName")).list();for (String string : list) {System.out.println(string);}
(2)查询大于1个属性时
      当投影的属性不止一个的时候,使用Projections的projectionList()方法来设置属性名称
/** * projetctionList()方法得到了ProjectionList对象,ProjectionList实现了Projection接口 */List<Object[]> list=session.createCriteria(Dept.class).setProjection(Projections.projectionList().add(Property.forName("deptNo")).add(Property.forName("deptName"))).list();for (Object[] item : list) {System.out.println(item[0]+"\t"+item[1]);}
(3)Projections常用的聚合查询方法
PropertyProjection Projections.groupProperty(String propertyName)分组PropertyProjection Projections.rowCount()统计记录数AggregateProjection Projections.avg(String propertyName)统计平均值AggregateProjection Projections.max(String propertyName)统计最大值AggregateProjection Projections.min(String propertyName)统计最小值CountProjection Projections.count(String propertyName)统计某一字段的非空记录数AggregateProjection Projections.sum(String propertyName)针对某一字段求和Hibernate API下载点击我
6.DetachedCriteria
             Criteria接口继承了CriteriaSpecification接口,而DetachedCriteria类实现了CriteriaSpecification接口,所以两者在使用的时候类似但是两者的创建不同:
             (1)Criteria是由Session对象创建
             (2)DetachedCriteria创建的时候不需要Session对象
      那么要DetachedCriteria又是何用呢?
       在常规的web项目中,有大量的动态条件查询,程序运行时会根据用户的选择动态生成查询语句。对于分层应用来说,Web层需要传递一个查询的条件列表到业务层,业务层获得条件列表之后一次取出条件进行查询,构造查询语句。
       关键是条件列表用什么构造?如果使用Map的话,Map传递的信息时非常有限的,只能传递键值对,无法传递究竟要怎样的条件运算,所以非常有限制性。
       所以DetachedCriteria就可以解决这个问题,将所有的查询条件封装成DetachedCriteria对象,然后传递到业务层,业务层可以再Session范围内通过DetachedCriteria对象直接构造查询。

     DetachedCriteria创建时不需要Session对象,只是在执行查询(调用list()方法)的时候需要

                    如:查询查询部门名称为“ACCOUNTING”并且名字中包含“l”的员工集合

/** * 1.使用forClass()静态方法创建对象,同样支持条件设置和连接查询 * 2.调用list()方法之前首先使用getExecutableCriteria()方法获取Criteria对象 */DetachedCriteria dCriteria=DetachedCriteria.forClass(Emp.class,"e").createAlias("e.dept", "d").add(Restrictions.eq("d.deptName", "ACCOUNTING")).add(Restrictions.ilike("empName", "l",MatchMode.ANYWHERE));List<Emp> list=dCriteria.getExecutableCriteria(session).list();for (Emp emp : list) {System.out.println(emp.getEmpName()+"\t"+emp.getDept().getDeptName());}

0 0
原创粉丝点击