zoukankan      html  css  js  c++  java
  • Hibernate第十篇【Hibernate查询详解、分页查询】

    前言

    在Hibernate的第二篇中只是简单地说了Hibernate的几种查询方式….到目前为止,我们都是使用一些简单的主键查询阿…使用HQL查询所有的数据….本博文主要讲解Hibernate的查询操作…

    get/load主键查询

    由于主键查询这个方法用得比较多,于是Hibernate专门为我们封装了起来…

    • get()立即查询
      • 这里写图片描述
    • load()懒加载
      • 这里写图片描述

    对象导航查询

    如果对象与对象之前存在一对多、多对一的关系的时候

    • 在以前SQL查询的时候:我们如果想要得到当前对象与另一对象的关联关系的时候,就必须用多表查询来得到数据
    • Hibernate提供了对象导航查询:我们可以使用主键查询完之后,得到的对象,直接使用对象得到集合…就可以得到对应的数据了
            // 对象导航查询
            Dept dept =  (Dept) session.get(Dept.class, 12);
            System.out.println(dept.getDeptName());
    
            //这里就可以得到部门对应的所有员工
            System.out.println(dept.getEmps());

    HQL查询

    Hibernate的第二篇已经讲解过了基本的概念了。在这里我们就直接看看怎么使用了。

    值得注意的是:

    • 在hbm.xml文件中的auto-import=”true” 要设置true。当然了,默认值就是ture
    • 如果是false,写hql的时候,要指定类的全名

    查询全部列

        //方式一:直接写对象
        Query q = session.createQuery("from Dept");
    
        //方式二:可以为对象取别名
        Query q = session.createQuery("select d from Dept d");
    

    值得注意的是:HQL不支持*号,下面的代码是错误的。

        //不能用*
        Query q = session.createQuery("select d from Dept d"); 
    

    查询指定的列

    值得注意的是:使用HQL查询指定的列,返回的是对象数组Object[]

            //只查询name和eatBanana列
            Query query = session.createQuery("select m.name,m.eatBanana from Monkey m");
            System.out.println(query.list());

    这里写图片描述

    封装对象

    前面测试了查询指定的列的时候,返回的是对象数组…可是对象数组我们不好操作啊…Hibernate还提供了将对象数组封装成对象的功能

    • JavaBean要有对应的构造函数
            Query query = session.createQuery("select new Monkey(m.name,m.eatBanana )from Monkey m");

    条件查询

    在SQL中条件查询我们也用得比较多,我们来看看HQL中的条件查询有什么新特性。

    占位符

    占位符就是指?号,我们在SQL中也常常用…

    
            Query query = session.createQuery("from Monkey m where m.name=?");
            //HQL是从0开始的
            query.setParameter(0, "大猴子");
    
            System.out.println(query.list());
    

    这里写图片描述


    命名参数

    HQL还支持命名参数查询!下面我们来看一下怎么用:

    语法::命名

    
            Query query = session.createQuery("from Monkey m where m.name=:monkeyName");
            //HQL是从0开始的
            query.setParameter("monkeyName", "大猴子");
            System.out.println(query.list());
    

    这里写图片描述


    范围查询

    范围查询就是使用between and关键字来查询特定范围的数据。。和SQL是一样的…

            Query q = session.createQuery("from Dept d where deptId between ? and ?");
            q.setParameter(0, 1);
            q.setParameter(1, 20);
            System.out.println(q.list());

    模糊查询

    模糊查询就是使用Like关键字进行查询,和SQL也是一样的。

    • %号要写在参数上,不能写带SQL上!
    
            //模糊
            Query q = session.createQuery("from Dept d where deptName like ?");
            q.setString(0, "%部%");
            System.out.println(q.list());

    聚合函数统计

    我们也经常会查询数据库中一共有多少条记录这样的需求。那么在HQL中怎么用呢?

    • HQL提供了uniqueResult()这么一个方法,返回只有一条记录的数据
            Query query = session.createQuery("select COUNT(*) from Monkey");
            Object o = query.uniqueResult();
            System.out.println(o);
    

    这里写图片描述


    分组查询

    分组查询和SQL是一样的…

    
            //-- 统计t_employee表中,每个部门的人数
            //数据库写法:SELECT dept_id,COUNT(*) FROM t_employee GROUP BY dept_id;
            // HQL写法
            Query q = session.createQuery("select e.dept, count(*) from Employee e group by e.dept");
            System.out.println(q.list());

    连接查询

    连接查询也就是多表查询…多表查询有三种

    • 内连接【等值连接】
    • 左外连接
    • 有外链接

    值得注意的是:连接查询返回的也是对象数组!

    
            //1) 内连接   【映射已经配置好了关系,关联的时候,直接写对象的属性即可】
            Query q = session.createQuery("from Dept d inner join d.emps");
    
            //2) 左外连接
            Query q = session.createQuery("from Dept d left join d.emps");
    
            //3) 右外连接
            Query q = session.createQuery("from Employee e right join e.dept");
            q.list();
    

    迫切连接

    由于连接查询返回的是对象数组,我们使用对象数组来操作的话会很不方便…既然是连接查询,那么对象与对象是肯定有关联关系的…于是乎,我们想把左表的数据填充到右表中,或者将右表的数据填充到左表中…使在返回的时候是一个对象、而不是对象数组!**HQL提供了**fetch关键字供我们做迫切连接

    
            //1) 迫切内连接    【使用fetch, 会把右表的数据,填充到左表对象中!】
            Query q = session.createQuery("from Dept d inner join fetch d.emps");
            q.list();
    
            //2) 迫切左外连接
            Query q = session.createQuery("from Dept d left join fetch d.emps");
            q.list();

    查询语句放在配置文件中【命名查询】

    我们可以在具体的映射配置文件中存放一些常用的语句。以Dept为例

    
        <!-- 存放sql语句,如果有<>这样的字符数据,需要使用CDATA转义! -->
        <query name="getAllDept">
            <![CDATA[
                from Dept d where deptId < ?
            ]]>
        </query>

    在程序中,我们可以获取配置文件配置的语句

            Query q = session.getNamedQuery("getAllDept");
            q.setParameter(0, 10);
            System.out.println(q.list());

    Criteria 查询

    Criteria是一种完全面向对象的查询

    Criteria使用的是add()来添加条件。条件又使用一个Restrictions类来封装

    
            Criteria criteria = session.createCriteria(Monkey.class);
            criteria.add(Restrictions.eq())
    

    我们来简单看一下Restrictions的方法:

    这里写图片描述

    都是一些大于、小于、等于之类的….Criteria查询就使用不了分组、连接查询了。


    SQLQuery本地SQL查询

    有的时候,我们可能表的结构十分复杂,如果使用关联映射的话,配置文件是十分臃肿的…因此,我们并不是把全部的数据表都使用映射的方式来创建数据表…

    这时,我们就需要用到SQLQuery来维护我们的数据了..

    SQLQuery是不能跨数据库的,因为Hibernate在配置的时候就指定了数据库的“方言”

    
            SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3");
    
            System.out.println(sqlQuery.list());

    返回的也是对象数组:

    这里写图片描述

    Hibernate也支持在SQLQuery中对数据进行对象封装..只要添加类型就行了

    
            SQLQuery sqlQuery = session.createSQLQuery("SELECT * FROM monkey_ limit 0,3").addEntity(Monkey.class);
    
            System.out.println(sqlQuery.list());
    
    

    这里写图片描述


    分页查询

    传统的SQL我们在DAO层中往往都是使用两个步骤来实现分页查询

    • 得到数据库表中的总记录数
    • 查询起始位置到末尾位数的数据

    Hibernate对分页查询也有很好地支持,我们来一下:

    
            Query query = session.createQuery("from Monkey");
    
            //得到滚动结果集
            ScrollableResults scroll = query.scroll();
            //滚动到最后一行
            scroll.last();
            int i = scroll.getRowNumber() + 1;
            System.out.println("总计路数:" + i);
    
            //设置分页位置
            query.setFirstResult(0);
            query.setMaxResults(3);
    
            System.out.println(query.list());
    • 提供了方法让我们设置起始位置和结束位置
    • 提供了ScrollableResults来得到滚动结果集,最终得到总记录数

    值得注意的是,滚动结果集是从0开始的,因此需要+1才可得到总记录数!

    这里写图片描述


    如果我们们使用的是SELECT COUNT(*) FROM 实体,我们可以通过uniqueResult()方法获取数据的唯一记录,得到的数据转换成Long类型即可。

        Long totalRecord = (Long) queryCount.uniqueResult();
  • 相关阅读:
    [luoguP1437] [HNOI2004]敲砖块(DP)
    [luoguP2073] 送花(set)
    [luoguP1783] 海滩防御(二分 || 最短路 || 最小生成树)
    [luoguP3068] [USACO13JAN]派对邀请函Party Invitations(stl大乱交)
    [luoguP1849] [USACO12MAR]拖拉机Tractor(spfa)
    数组
    String
    学不会的JVM
    异常
    反射
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7202960.html
Copyright © 2011-2022 走看看