zoukankan      html  css  js  c++  java
  • hibernate的Criteria Query(转)

    当查询数据时,人们往往需要设置查询条件。在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 = session.createCriteria(Student.class); //生成一个Criteria对象
    cr.add(Restrictions.eq("name""Bill"));//等价于where name=’Bill’
    List list = cr.list();
    Student stu 
    = (Student)list.get(0);
    System.out.println(stu.getName());

    1.常用的查询限制方法

    在例程9-1中,Restrictions.eq()方法表示equal,即等于的情况。Restrictions类提供了查询限制机制。它提供了许多方法,以实现查询限制。这些方法及其他一些criteria常用查询限制方法列于表9-1中。

    表9-1  Criteria Query常用的查询限制方法

       

       

    Restrictions.eq()

    equal=

    Restrictions.allEq()

    参数为Map对象,使用key/value进行多个等于的对比,相当于多个Restrictions.eq()的效果

    Restrictions.gt()

    greater-than, >

    Restrictions.lt()

    less-than, <

    Restrictions.le()

    less-equal, <=

    Restrictions.between()

    对应SQLbetween子句

    Restrictions.like()

    对应SQLlike子句

    Restrictions.in()

    对应SQLin子句

    Restrictions.and()

    and关系

    Restrictions.or()

    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 = session.createCriteria(Student.class);
    cr.add(Restrictions.like(“name”, “t%”))
    List list = cr.list();
    Student stu = (Student)list.get(0);
    或者使用另一种方式:
     Criteria cr = session.createCriteria(Student.class);
    cr.add(Restrictions.like(“name”, “t”, MatchMode.START))
    List list = cr.list();
    Student stu = (Student)list.get(0);
    例2:查询学生姓名在Bill, Jack和Tom之间的所有Student对象。
     String[] names = {“Bill”, “Jack”, “Tom”}
    Criteria cr = session.createCriteria(Student.class);
    cr.add(Restrictions.in(“name”, names))
    List list = cr.list();
    Student stu = (Student)list.get(0);
    例3:查询学生的年龄age等于22或age为空(null)的所有Student对象。
    Criteria cr = session.createCriteria(Student.class);
    cr.add(Restrictions.eq(“age”, new Integer(22));
    cr.add(Restrictions.isNull(“age”));
    List list = cr.list();
    Student stu = (Student)list.get(0);
    例4:查询学生姓名以字母F开头的所有Student对象,并按姓名升序排序。
    Criteria cr = session.createCriteria(Student.class);
    cr.add(Restrictions.like(“name”, “F%”);
    cr.addOrder(Order.asc(“name”));
    List list = cr.list();
    Student stu = (Student)list.get(0);

    调用Order.asc的方法应是Criteria的addOrder()方法。

    使用add()方法加入条件时,预设是使用and来组合条件,如果要用or的方式来组合条件,则可以使用Restrictions.or()方法,例如结合age等于(eq)20或(or)age为空(isNull)的条件:

    1. Criteria criteria = session.createCriteria(User.class);  
    2. criteria.add(Restrictions.or(  
    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进行查询,并使用org.hibernate.criterion.Order对结果进行排序,例如使用Oder.asc(),指定根据”age”由小到大排序(反之则使用desc()):

    1. Criteria criteria = session.createCriteria(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 = session.createCriteria(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 ?, ?

    统计动作
    您可以对查询结果进行统计动作,使用 org.hibernate.criterion.Projections的avg()、rowCount()、count()、max()、min ()、 countDistinct()等方法,再搭配Criteria的setProjection()方法加入条件设定,例如对查询结果的"age"作平均:

    1. Criteria criteria = session.createCriteria(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 = session.createCriteria(User.class);  
    2. criteria.setProjection(Projections.groupProperty("age"));  
    3. List users = criteria.list(); 

    上面的程式将由Hibernate自动产生SQL的group by子句进行分组计算:

    Hibernate: select this_.age as y0_ from T_USER this_ group by this_.age

    如果想同时结合统计与分组功能,则可以使用org.hibernate.criterion.ProjectionList,例如下面的程式会计算每个年龄各有多少个人:

    1. ProjectionList projectionList = Projections.projectionList();  
    2. projectionList.add(Projections.groupProperty("age"));  
    3. projectionList.add(Projections.rowCount());  
    4.  
    5.  
    6. Criteria criteria = session.createCriteria(User.class);  
    7. criteria.setProjection(projectionList);  
    8. 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.  
    4. Criteria criteria = session.createCriteria(User.class);  
    5. criteria.add(Example.create(user));  
    6.  
    7. List users = criteria.list();  

    Criteria进阶查询中,您可以透过 org.hibernate.criterion.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 = session.createCriteria(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 = session.createCriteria(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 '%2005'
    可以使用Criteria的API完成同样的功能,如下所示:
    Criteria cr = session.createCriteria(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 '%2005'
  • 相关阅读:
    平均值的最值化
    GCJ 2008 R3 C 二分图匹配
    BZOJ 1013 高斯消元
    NOIP2015 d2T3 二分+树上前缀和
    9.7集训 总结
    BZOJ 1026
    BZOJ 3223
    NOIP前夕:codevs,关路灯
    NOIP前夕:codevs,解药还是毒药
    NOIP前夕:codevs,修剪花卉
  • 原文地址:https://www.cnblogs.com/Fskjb/p/1614810.html
Copyright © 2011-2022 走看看