Hibernate中CriteriaQuery查询详解【转】
当查询数据时,⼈们往往需要设置查询条件。在SQL或HQL语句中,查询条件常常放在where⼦句中。此外,Hibernate还⽀持Criteria查询(Criteria Query),这种查询⽅式把查询条件封装为⼀个Criteria对象。在实际应⽤中,使⽤Session的createCriteria()⽅法构建⼀个
org.hibernate.Criteria实例,然后把具体的查询条件通过Criteria的add()⽅法加⼊到Criteria实例中。这样,程序员可以不使⽤SQL甚⾄HQL的情况下进⾏数据查询,如例程9-1所⽰。
例程9-1 Criteria应⽤实例
代码
Criteria cr = ateCriteria(Student.class); //⽣成⼀个Criteria对象
cr.add(Restrictions.eq("name", "Bill"));//等价于where name=’Bill’
List list = cr.list();
Student stu = ((0);
System.out.Name());
1.常⽤的查询限制⽅法
在例程9-1中,Restrictions.eq()⽅法表⽰equal,即等于的情况。Restrictions类提供了查询限制机制。它提供了许多⽅法,以实现查询限制。这些⽅法及其他⼀些criteria常⽤查询限制⽅法列于表9-1中。
表9-1 Criteria Query常⽤的查询限制⽅法
⽅法说明
Restrictions.eq()equal,=
Restrictions.allEq()参数为Map对象,使⽤key/value进⾏多个等于的对⽐,相当于多个Restrictions.eq()的效果
<()greater-than, >
Restrictions.lt()less-than, <
Restrictions.le()less-equal, <=
Restrictions.between()对应SQL的between⼦句
Restrictions.like()对应SQL的like⼦句
Restrictions.in()对应SQL的in⼦句
Restrictions.and()and关系
<()or关系
Restrictions.isNull()判断属性是否为空,为空返回true,否则返回false
Restrictions.isNotNull()与Restrictions.isNull()相反
Order.asc()根据传⼊的字段进⾏升序排序
Order.desc()根据传⼊的字段进⾏降序排序
MatchMode.EXACT字符串精确匹配,相当于“like 'value'”
MatchMode.ANYWHERE字符串在中间位置,相当于“like '%value%'”
MatchMode.START字符串在最前⾯的位置,相当于“like 'value%'”
MatchMode.END字符串在最后⾯的位置,相当于“like '%value'”
例1:查询学⽣名字以t开头的所有Student对象。
Criteria cr = ateCriteria(Student.class);
cr.add(Restrictions.like(“name”, “t%”))
List list = cr.list();
Student stu = ((0);
或者使⽤另⼀种⽅式:
Criteria cr = ateCriteria(Student.class);
cr.add(Restrictions.like(“name”, “t”, MatchMode.START))
List list = cr.list();
Student stu = ((0);
例2:查询学⽣姓名在Bill, Jack和Tom之间的所有Student对象。
String[] names = {“Bill”, “Jack”, “Tom”}
Criteria cr = ateCriteria(Student.class);
cr.add(Restrictions.in(“name”, names))
List list = cr.list();
Student stu = ((0);
例3:查询学⽣的年龄age等于22或age为空(null)的所有Student对象。
Criteria cr = ateCriteria(Student.class);
cr.add(Restrictions.eq(“age”, new Integer(22));
cr.add(Restrictions.isNull(“age”));
List list = cr.list();
Student stu = ((0);
例4:查询学⽣姓名以字母F开头的所有Student对象,并按姓名升序排序。
Criteria cr = ateCriteria(Student.class);
cr.add(Restrictions.like(“name”, “F%”);
cr.add(Restrictions.like(“name”, “F%”);
cr.addOrder(Order.asc(“name”));
List list = cr.list();
Student stu = ((0);
调⽤Order.asc的⽅法应是Criteria的addOrder()⽅法。
使⽤add()⽅法加⼊条件时,预设是使⽤and来组合条件,如果要⽤or的⽅式来组合条件,则可以使⽤()⽅法,例如结合age等于(eq)20或(or)age为空(isNull)的条件:
1. Criteria criteria = ateCriteria(User.class);
2. criteria.(
3. Restrictions.eq("age", new Integer(20)),
4. Restrictions.isNull("age")
5. ));
6. List users = criteria.list();
观察所产⽣的SQL语句,将使⽤where与or⼦句完成SQL的条件查询:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=? or this_.age is null)
使⽤Criteria进⾏查询时,不仅仅能组合出SQL中where⼦句的功能,还可以组合出如排序、统计、分组等的查询功能。这就是Criteria进阶查询。
排序
您可以使⽤Criteria进⾏查询,并使⽤iterion.Order对结果进⾏排序,例如使⽤Oder.asc(),指定根据”age”由⼩到⼤排序(反之则使⽤desc()):
1. Criteria criteria = ateCriteria(User.class);
2. criteria.addOrder(Order.asc("age"));
3. List users = criteria.list();
注意在加⼊Order条件时,使⽤的是addOrder()⽅法,⽽不是add()⽅法,在产⽣SQL语句时,会使⽤order by与asc(desc)来进⾏排序指定:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ order by this_.age asc
限定查询笔数
Criteria的setMaxResults()⽅法可以限定查询回来的笔数,如果配合setFirstResult()设定传回查询结果第⼀笔资料的位置,就可以实现简单的分页,例如传回第51笔之后的50笔资料(如果有的话):
1. Criteria criteria = ateCriteria(User.class);
2. criteria.setFirstResult(51);
3. criteria.setMaxResults(50);
4. List users = criteria.list();
根据您所指定得资料库,Hibernate将⾃动产⽣与资料库相依的限定笔数查询⼦句,例如在MySQL中,将使⽤limit产⽣以下的SQL语句:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ limit ?, ?
统计动作
您可以对查询结果进⾏统计动作,使⽤ iterion.Projections的avg()、rowCount()、count()、max()、min ()、 countDistinct()等⽅法,再搭配Criteria的setProjection()⽅法加⼊条件设定,例如对查询结果的"age"作平均:
1. Criteria criteria = ateCriteria(User.class);
2. criteria.setProjection(Projections.avg("age"));
3. List users = criteria.list();
上⾯的程式将由Hibernate⾃动产⽣SQL的avg函数进⾏平均计算:
Hibernate: select avg(this_.age) as y0_ from T_USER this_
分组
还可以配合Projections的groupProperty()来对结果进⾏分组,例如以"age"进⾏分组,也就是如果资料中"age"如果有 20、20、25、30,则以下会显⽰20、25、30:
1. Criteria criteria = ateCriteria(User.class);
2. criteria.upProperty("age"));
3. List users = criteria.list();
上⾯的程式将由Hibernate⾃动产⽣SQL的group by⼦句进⾏分组计算:
Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age
queryselectorall用法如果想同时结合统计与分组功能,则可以使⽤iterion.ProjectionList,例如下⾯的程式会计算每个年龄各有多少个⼈:
1. ProjectionList projectionList = Projections.projectionList();
2. projectionList.upProperty("age"));
3. projectionList.wCount());
4. Criteria criteria = ateCriteria(User.class);
5. criteria.setProjection(projectionList);
6. List users = criteria.list();
观察所产⽣的SQL语句,将使⽤group by先进⾏分组,再针对每个分组进⾏count函数的计数,
Hibernate: select this_.age as y0_, count(*) as y1_ from T_USER this_ group by this_.age
根据已知物件进⾏查询
设定查询条件并⾮⼀定要使⽤Restrictions,如果属性条件很多,使⽤Restrictions也不⽅便,如果有⼀个已知的物件,则可以根据这个物件作为查询的依据,看看是否有属性与之类似的物件,例如:
1. User user = new User();
2. user.setAge(new Integer(30));
3. Criteria criteria = ateCriteria(User.class);
4. criteria.ate(user));
5. List users = criteria.list();
Criteria进阶查询中,您可以透过 iterion.Example的create()⽅法来建⽴Example实例,Example实作了 Criteria介⾯,因此可以使⽤add()⽅法加⼊⾄Criteria条件设定之中,Hibernate将⾃动过滤掉空属性,根据已知物件上已设定的属性,判定是否产⽣于where⼦句之中:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where (this_.age=?)
设定SQL范本
如果您了解如何撰写SQL语句,想要设定⼀些Hibernate产⽣SQL时的范本,您也可以使⽤Restrictions的sqlRestriction()⽅法,提供SQL语法范本作限定查询,例如查询name以cater开头的资料:
1. Criteria criteria = ateCriteria(User.class);
2. criteria.add(Restrictions.sqlRestriction(
3. "{alias}.name LIKE (?)", "cater%", Hibernate.STRING));
4. List users = criteria.list();
其中alias将被替换为与User类别相关的名称,⽽? 将被替换为cater%,也就是第⼆个参数所提供的值,sqlRestriction()⽅法第⼀个参数所设定的是where⼦句的部份,所以在SQL撰写时,不必再写where,观察所产⽣的SQL语句,将使⽤您所设定的SQL范本作为基础,来完成SQL的条件查询:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.name LIKE (?)
如果有多个查询条件,例如between⼦句的查询,则可以如下:
1. Criteria criteria = ateCriteria(User.class);
2. Integer[] ages = {new Integer(20), new Integer(40)};
3. Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};
4. criteria.add(Restrictions.sqlRestriction(
5. "{alias}.age BETWEEN (?) AND (?)", ages, types));
6. List users = criteria.list();
观察所产⽣的SQL语句如下:
Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_ where this_.age BETWEEN (?) AND (?)
2.连接限制
在Criteria 查询中使⽤FetchMode来实现连接限制。在HQL语句中,可以通过fetch关键字来表⽰预先抓取(Eager fetching),如下所⽰:
from Group g
left join fetch g.students s
where g.name like ' 05'
可以使⽤Criteria的API完成同样的功能,如下所⽰:
Criteria cr = ateCriteria(Group.class);
cr.setFetchMode(“students”, FetchMode.EAGER);
cr.add(Restrictions.like(“name”, “2005”, MatchMode.END))
List list = cr.list();
以上两种⽅式编写的代码,都使⽤相同的SQL语句完成它们的功能,如下所⽰:
select g.*, s.* from Group g
left outer join Student s
on g.id = s.group_id
where g.name like ' 05' );
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论