zoukankan      html  css  js  c++  java
  • hibernate 查询方式汇总

    主要摘自  http://blog.sina.com.cn/s/blog_7ffb8dd501014a6o.html http://blog.csdn.net/xingtianyiyun/article/details/7703429

    Hibernate总的来说共有三种查询方式:HQL、QBC和SQL三种。但是细分可以有如下几种:

    一、HQL查询方式

        这一种我最常用,也是最喜欢用的,因为它写起来灵活直观,而且与所熟悉的SQL的语法差不太多。条件查询、分页查询、连接查询、嵌套查询,写起来与SQL 语法基本一致,唯一不同的就是把表名换成了类或者对象。其它的,包括一些查询函数(count(),sum()等)、查询条件的设定等,全都跟SQL语法 一样。
    ###注意:
         在hql中关键字不区分大小写,但是属性和类名区分大小写
    示例1:

       //from后面是对象,不是表名
       String hql="from Admin as admin where admin.aname=:name";//使用命名参数,推荐使用,易读。
       Query query=s.createQuery(hql);
       query.setString("name", name);
       List<Admin> list=query.list();

     
    ######!!!!!!!!!!!!!对于多对一关系查询:
     
    String hql = "from Student where Class.className = '二班'";
    (Student实体类中含有Class对象的引用。这样相当于两张表的联合查询

    示例2(分页查询)
        Query query = session.createQuery("from Customer c order by c.name asc");
       query.setFirstResult(0);
       query.setMaxResults(10);
       List result = query.list();
        说明:
      
    –setFirstResult(int firstResult):设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0。默认情况下,Query和Criteria接口从查询结果中的第一个对象,也就是索引位置为0的对象开始检索。 

        –setMaxResult(int maxResults):设定一次最多检索出的对象数目。默认情况下,Query和Criteria接口检索出查询结果中所有的对象。

    适用情况:常用方法,比较传统,类似jdbc。缺点:新的查询语言,适用面有限,仅适用于Hibernate框架。

    二、QBC(Query By Criteria) 查询方式
       这种方式比较面向对象方式,重点是有三个描述条件的对象:Restrictions,Order,Projections。使用QBC查询,一般需要以下三个步骤:
       1、 使用Session实例 的createCriteria()方法创建Criteria对象
       2、使用工具类Restrictions的方法为Criteria对象设置查询条件,Order工具类的方法设置排序方式,Projections工具类的方法进行统计和分组。
       3、 使用Criteria对象的list()方法进行查询并返回结果
    Restrictions类的常用方法:

    Restrictions类的常用方法:

    方法名称
    描述
    Restrictions.eq 等于
    Restrictions.allEq 使用Map,Key/Valu进行多个等于的比对
    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关系
    Restrictions.sqlRestriction SQL限定查询

    Order类的常用方法:

    方法名称
    描述
    Order.asc 升序
    Order.desc 降序

    Projections类的常用方法

    方法名称
    描述
    Projections.avg 求平均值
    Projections.count 统计某属性的数量
    Projections.countDistinct 统计某属性不同值的数量
    Projections.groupProperty 指定某个属性为分组属性
    Projections.max 求最大值
    Projections.min 求最小值
    Projections.projectionList 创建一个ProjectionList对象
    Projections.rowCount 查询结果集中的记录条数
    Projections.sum 求某属性的合计


    示例:

       Criteria c=s.createCriteria(Admin.class);
       c.add(Restrictions.eq("aname",name));//eq是等于,gt是大于,lt是小于,or是或
       c.add(Restrictions.eq("apassword", password));
       List<Admin> list=c.list();


    示例2(分页查询)
        Criteria criteria = session.createCriteria(Customer.class);
      criteria.addOrder( Order.asc("name") ); //排序方式
      criteria.setFirstResult(0);
      criteria.setMaxResults(10);
      List result = criteria.list()
     
    适用情况:面向对象操作,革新了以前的数据库操作方式,易读。缺点:适用面较HQL有限。

    三、QBE(Query By Example)例子查询方式
       将一个对象的非空属性作为查询条件进行查询。
     示例:

        User user = new User();
        user.setName("ijse");

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

       适用情况:面向对象操作。   缺点:适用面较HQL有限,不推荐。

    四、DetachedCriteria:离线条件查询
       离线查询就是建立一个DetachedCriteria对象,将查询的条件等指定好,然后在session.beginTransaction()后将这个对象传入。通常这个对象可以在表示层建立,然后传入业务层进行查询。
      1、建立DetachedCriteria对象
        DetachedCriteria dc = DetachedCriteria.forClass(User.class);
        int id = 1;
        if (id != 0)
        dc.add(Restrictions.eq("id", id));
        Date age = new Date();
       if (age != null)
        dc.add(Restrictions.le("birthday", age));
       List users = dc(dc);//执行查询
      System.out.println("离线查询返回结果:" + users);
     2、执行查询
       static List dc(DetachedCriteria dc) {
           Session s = HibernateUtil.getSession();
           Criteria c = dc.getExecutableCriteria(s);
           List rs = c.list();

           s.close();
           return rs;
         }
       适用情况:面向对象操作,分离业务与底层,不需要字段属性摄入到Dao实现层。  缺点:适用面较HQL有限。

    五、命名查询
      1、在数据映射元文件中进行配置如下:
     <?xml version="1.0" encoding="utf-8"?>
      <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
      "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
      <hibernate-mapping>
        <class name="com.sy.vo.User" table="user" catalog="news">
       ....
        </class>
        <!-- 命名查询:定义查询条件 -->
        <query name="getUserById">
         <![CDATA[from User where id=:id]]>
        </query>

        <!-- 命名查询中使用sql,不推荐使用,影响跨数据库
        <sql-query name="getUserById2">
         <![CDATA[select * from User where ]]>
        </sql-query> -->

    </hibernate-mapping>
      2、在java代码中写入:
      static List namedQuery(int id) {
        Session s = HibernateUtil.getSession();
        Query q = s.getNamedQuery("getUserById");
        q.setInteger("id", id);

        return q.list();
       }
      适用情况:万能方法,有点像ibatis轻量级框架的操作,方便维护。 

       缺点:不面向对象。基于hql和sql,有一定缺陷。

    六、SQL查询
       示例:
      static List sql() {
       Session s = HibernateUtil.getSession();
        Query q = s.createSQLQuery("select * from user").addEntity(User.class);
        List<User> rs = q.list();

        s.close();
        return rs;
        }
    适用情况:不熟悉HQL的朋友,又不打算转数据库平台的朋友,万能方法   缺点:破坏跨平台,不易维护,不面向对象。

    七、OID查询方式
       
    按照对象的OID来检索对象。Session的get()和load()方法提供了这种功能。如果在应用程序中事先知道了OID,就可以使用这种检索对象的方式。 

     

    八、Query.iterator的N+1查询(基于一的HQL,多见于一对多、多对多的关联映射)
      N + 1问题,在默认情况下,使用query.iterate查询,有可以能出现N+1问题
       所谓的N+1是在查询的时候发出了N+1条sql语句
       1: 首先发出一条查询对象id列表的sql
       N: 根据id列表到缓存中查询,如果缓存中不存在与之匹配的数据,那么会根据id发出相应的sql语句
    * list和iterate的区别?
       * list每次都会发出sql语句,list会向缓存中放入数据,而不利用缓存中的数据
       * iterate:在默认情况下iterate利用缓存数据,但如果缓存中不存在数据有可以能出现N+1问题

      示例:Query q=session.createQuery(“from UserInfo”);
         Iterator<UserInfo> list=q.iterate();

         While(list.hasNext()) {
         UserInfo st = (UserInfo) it.next();
         System.out.println(st.getName());
        }
    避免N+1查询解决方法:
        1、可以将fetch抓取数据的属性改为“join”,来避免N+1次的查询;
        2、使用二级缓存
    九、复查查询(基于二:QBC的深度查询)
        复合查询就是在原有查询的基础上再进行查询,

        可以调用Criteria对象的createCriteria()方法在这个Criteria对象的基础上再进行查询。
        示例:Session session = SessionFactory.getCurrentSession();
                User user = new User();
                Transaction ts = session.beginTransaction();
                try  {
                   Criteria criteria1 = session.createCriteria(Room.class);
                   Criteria  criteria2 =criterial.createCriteria("User");
                   criteria2.add(Restrictions.eq("name",new String("ijse"));

                   user= (User) criteria.list().get(0);
                   session.commit();
               } catch (HibernateException ex) {
                    ts.rollBack();
                    ex.printStackTrace();
               }
              System.out.println(user.getName());

    ======================================================================================================

    您可以使用Criteria进行查询,并使用Order对结果进行排序,例如使用Oder.asc()由小到大排序(反之则使用desc()):

    Criteria criteria = session.createCriteria(User.class);

    criteria.addOrder(Order.asc("age"));

    List users = criteria.list();

    setMaxResults()方法可以限定查询回来的笔数,如果配合setFirstResult()设定传回查询结果第一笔资料的位置,就可以实现简单的分页,例如传回第51笔之后的50笔资料(如果有的话):

    Criteria criteria = session.createCriteria(User.class);

    criteria.setFirstResult(51);

    criteria.setMaxResult(50);

    List users = criteria.list();

    您可以对查询结果进行统计动作,使用Projections的avg()、rowCount()、count()、max()、min()、 countDistinct()等方法,例如对查询结果的"age"作平均:

    Criteria criteria = session.createCriteria(User.class);

    criteria.setProjection(Projections.avg("age"));

    List users = criteria.list();

    Iterator iterator = users.iterator();

    while(iterator.hasNext()) {

        System.out.println(iterator.next());      

    }

    还可以配合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();

    Iterator iterator = users.iterator();

    while(iterator.hasNext()) {

        System.out.println(iterator.next());      

    }

    如果想结合统计与分组功能,则可以使用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();

    Iterator iterator = users.iterator();

    while(iterator.hasNext()) {

        Object[] o = (Object[]) iterator.next();

        System.out.println(o[0] + " " + o[1]);

    }

    如果有一个已知的物件,则可以根据这个物件作为查询的依据,看看是否有属性与之类似的物件,例如:

    User user = new User();

    user.setAge(new Integer(30));

    Criteria criteria = session.createCriteria(User.class);

    criteria.add(Example.create(user));

    List users = criteria.list();

    Iterator iterator = users.iterator();

    System.out.println("id name/age");

    while(iterator.hasNext()) {

        User ur = (User) iterator.next();

        System.out.println(ur.getId() +

                                    " " + ur.getName() +

                                    "/" + ur.getAge());           

    }

    在这个例子中,user物件中有已知的属性"age"为30,使用Example会自动过滤掉user的空属性,并以之作为查询的依据,也就是找出 "age"同为30的资料。

    Criteria可以进行复合查询,即在原有的查询基础上再进行查询,例如在Room对User的一对多关联中,在查询出所有的Room资料之后,希望再查询users中"age"为30的user资料:

    Criteria roomCriteria = session.createCriteria(Room.class);

    Criteria userCriteria = roomCriteria.createCriteria("users");

    userCriteria.add(Restrictions.eq("age", new Integer(30)));

    List rooms = roomCriteria.list(); // 只列出users属性中有user之"age"为30的Room

    Iterator iterator = rooms.iterator();

    hibernte criteria只查询表的的某个字段:

    1. Criteria   criteria=session.createCriteria(User.class);   
    2.  ProjectionList   proList   =   Projections.projectionList();//设置投影集合   
    3.   proList.add(Projections.Property( "userName "));   
    4.   proList.add(Projections.Property( "password "));   
    5.   criteria.setProjection(proList);  

    统计+分组 +关联查询

    Criteria c = getSession().createCriteria(Infos.class);
            c.add(Restrictions.in("infoType", infoType));
            c.add(Restrictions.eq("infoStatus", 3));
            c.setProjection(Projections.projectionList()
                    .add(Projections.groupProperty("infoType"))
                    .add(Projections.max("infoTime"),"infoTime"));
            List<Object> l = c.list();
            Object[] types=new Object[l.size()];
            Timestamp[] times=new Timestamp[l.size()];
            int i=0;
            for(Object o:l){
                Object[]obj=(Object[]) o;
                types[i]=obj[0];
                times[i]=(Timestamp) obj[1];
                i++;
            }
            c=getSession().createCriteria(Infos.class);
            c.add(Restrictions.in("infoType", types))
            .add(Restrictions.in("infoTime",times));
            List<Infos> list=c.list();


    注意 :1` pubStationsV  是   PubTabTimeDate持久内中  关联对象名  , 不是 持久类名 

                 2`  projectionList 只能使用一次 多次没用

                         3` 别名是用很关键(pv) 否则 管理表中属性 找不到  会报错

    Session session = pubTabTimeDateDao.getCurrentSession();
            Criteria c = session.createCriteria(PubTabTimeDate.class,"p");
            ProjectionList projectionList=Projections.projectionList();
            projectionList.add(Projections.distinct(Projections.property("p.fstationnum")));
            projectionList.add(Projections.property("pv.faddress"));
            c.addOrder(Order.desc("p.fstationnum"))
            .setFirstResult(0)
            .setMaxResults(30);
            Criteria cc = c.createCriteria("pubStationsV","pv");
            c.setProjection(projectionList);
            List list = cc.list();

    ----------- 赠人玫瑰,手有余香     如果本文对您有所帮助,动动手指扫一扫哟   么么哒 -----------


    未经作者 https://www.cnblogs.com/xin1006/ 梦相随1006 同意,不得擅自转载本文,否则后果自负
  • 相关阅读:
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    PatentTips
    How to build and run ARM Linux on QEMU from scratch
    How to debug Android Native Application with eclipse
  • 原文地址:https://www.cnblogs.com/xin1006/p/3800070.html
Copyright © 2011-2022 走看看