zoukankan      html  css  js  c++  java
  • hibernate 中 Criteria 的使用介绍

    本文来自http://www.blogjava.net/jjshcc/archive/2010/08/16/329046.html?opt=admin

    要对资料库管理系统进行操作,最基本的就是使用SQL(Standard Query Language)语句,大部份的资料库都支援标准的SQL语句,然而也有一些特定于资料库的SQL语句,应用程式配合SQL语句进行资料库查询时,若使用到特定于资料库的SQL语句,程式本身会有相依于特定资料库的问题。

    使用Hibernate时,即使您不了解SQL的使用与撰写,也可以使用它所提供的API来进行SQL语句查询,org.hibernate.Criteria对SQL进行封装,您可以从Java物件的观点来组合各种查询条件,由Hibernate自动为您产生SQL语句,而不用特别管理SQL与资料库相依的问题。

    以最基本的查询来说,如果您想要查询某个物件所对应的资料表中所有的内容,您可以如下进行查询:

    Criteria criteria = session.createCriteria(User.class);
    List users = criteria.list();

    for(Iterator it = users.iterator(); it.hasNext(); ) {
    User user = (User) it.next();
    System.out.println(user.getId() +
    " "t " + user.getName() +
    "/" + user.getAge());
    }


    Criteria建立后,若不给予任何的条件,预设是查询物件所对应表格之所有资料,如果您执行以上的程式片段,并于设定档中设定了了Hibernate的”show_sql”属性,则可以在主控下看到以下的SQL语句之产生:

    Hibernate: select this_.id as id0_0_, this_.name as name0_0_, this_.age as age0_0_ from T_USER this_

    Criteria基本查询条件设定

    org.hibernate.Criteria实际上是个条件附加的容器,如果想要设定查询条件,则要使用org.hibernate.criterion.Restrictions的各种静态方法传回org.hibernate.criterion.Criteria实例,传回的每个org.hibernate.criterion.Criteria实例代表着一个条件,您要使用org.hibernate.Criteria的add()方法加入这些条件实例,例如查询”age”大于20且小于40的资料:

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Restrictions.gt("age", new Integer(20)));
    criteria.add(Restrictions.lt("age", new Integer(40)));
    List users = criteria.list();

    for(Iterator it = users.iterator(); it.hasNext(); ) {
    User user = (User) it.next();
    System.out.println(user.getId() +
    " "t " + user.getName() +
    "/" + user.getAge());
    }

    Restrictions的gt()方法表示大于(great than)的条件,而lt表示小于(less than)的条件,执行以上程式片段,观察所产生的SQL语句,将使用where与and子句产来完成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>? and this_.age

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

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Restrictions.or(
    Restrictions.eq("age", new Integer(20)),
    Restrictions.isNull("age")
    ));
    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)

    您也可以使用Restrictions.like()方法来进行SQL中like子句的功能,例如查询”name”中名称为”just”开头的资料:

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Restrictions.like("name", "just%"));
    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_.name like ?

    Restrictions的几个常用限定查询方法如下表所示:

    方法 说明
    Restrictions.eq 等于
    Restrictions.allEq 使用Map,使用key/value进行多个等于的比对
    Restrictions.gt 大于 >
    Restrictions.ge 大于等于 >=
    Restrictions.lt 小于 <
    Restrictions.le 小于等于 <=
    Restrictions.between 对应SQL的BETWEEN子句
    Restrictions.like 对应SQL的LIKE子句
    Restrictions.in 对应SQL的in子句
    Restrictions.and and关係
    Restrictions.or or关係

    Criteria进阶查询条件设定

    使用Criteria进行查询时,不仅仅能组合出SQL中where子句的功能,还可以组合出如排序、统计、分组等的查询功能。

    排序

    您可以使用Criteria进行查询,并使用org.hibernate.criterion.Order对结果进行排序,例如使用Oder.asc(),指定根据”age”由小到大排序(反之则使用desc()):

    Criteria criteria = session.createCriteria(User.class);
    criteria.addOrder(Order.asc("age"));
    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笔资料(如果有的话):

    Criteria criteria = session.createCriteria(User.class);
    criteria.setFirstResult(51);
    criteria.setMaxResults(50);
    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"作平均:

    Criteria criteria = session.createCriteria(User.class);
    criteria.setProjection(Projections.avg("age"));
    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:

    Criteria criteria = session.createCriteria(User.class);
    criteria.setProjection(Projections.groupProperty("age"));
    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,例如下面的程式会计算每个年龄各有多少个人:

    ProjectionList projectionList = Projections.projectionList();
    projectionList.add(Projections.groupProperty("age"));
    projectionList.add(Projections.rowCount());

    Criteria criteria = session.createCriteria(User.class);
    criteria.setProjection(projectionList);
    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也不方便,如果有一个已知的物件,则可以根据这个物件作为查询的依据,看看是否有属性与之类似的物件,例如:

    User user = new User();
    user.setAge(new Integer(30));

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Example.create(user));

    List users = criteria.list();

    您可以透过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开头的资料:

    Criteria criteria = session.createCriteria(User.class);
    criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));
    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子句的查询,则可以如下:

    Criteria criteria = session.createCriteria(User.class);
    Integer[] ages = {new Integer(20), new Integer(40)};
    Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};
    criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));
    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 (?)

    使用DetchedCriteria

    Criteria与Session绑定,其生命週期跟随着Session结束而结束,使用Criteria时进行查询时,每次都要于执行时期动态建立物件,并加入各种查询条件,随着Session的回收,Criteria也跟着回收。

    为了能够重複使用Criteria物件,在Hibernate 3中新增了org.hibernate.criterion.DetchedCriteria,您可以先建立DetchedCriteria实例,并加入各种查询条件,并于需要查询时再与Session绑定,获得一个绑定Session的Criteria物件,例如:

    // 先建立DetchedCriteria物件
    DetachedCriteria detchedCriteria = DetachedCriteria.forClass(User.class);
    // 加入查询条件
    detchedCriteria.add(Restrictions.ge("age",new Integer(25)));

    Session session = sessionFactory.openSession();
    // 绑定Session并返回一个Criteria实例
    Criteria criteria = detchedCriteria.getExecutableCriteria(session);

    List users = criteria.list();

    结论

    Hibernate的Criteria API可以让您使用物件的方式,组合出查询资料库系统的条件,Hibernate会自动依您所使用的资料库,动态产生SQL语句,让您的应用程式在存取资料库时,不致于因撰写了特定的SQL而相依于特定的资料库,如果您的开发人员不熟悉SQL语句的撰写,也可以试着使用Criteria来解决查询资料库的需求。

  • 相关阅读:
    python的参数传递
    django的objects级别的权限控制
    django如何将mysql数据库转化为model
    django的orm查询使用in的保序
    多用户OFDM系统资源分配研究
    第一代到第四代多址技术:从FDMA、TDMA、CDMA到OFDMA
    Kaggle比赛总结
    4 二维数组中的查找 JavaScript
    5 替换空格 JavaScript
    简单的HTTP协议
  • 原文地址:https://www.cnblogs.com/qlong8807/p/2959150.html
Copyright © 2011-2022 走看看