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来解决查询资料库的需求。

  • 相关阅读:
    封装成帧、帧定界、帧同步、透明传输(字符计数法、字符串的首尾填充法、零比特填充的首尾标志法、违规编码法)
    计算机网络之数据链路层的基本概念和功能概述
    物理层设备(中继器、集线器)
    计算机网络之传输介质(双绞线、同轴电缆、光纤、无线电缆、微波、激光、红外线)
    计算机网络之编码与调制
    0953. Verifying an Alien Dictionary (E)
    1704. Determine if String Halves Are Alike (E)
    1551. Minimum Operations to Make Array Equal (M)
    0775. Global and Local Inversions (M)
    0622. Design Circular Queue (M)
  • 原文地址:https://www.cnblogs.com/qlong8807/p/2959150.html
Copyright © 2011-2022 走看看