zoukankan      html  css  js  c++  java
  • Hibernate之检索方式

    时间:2017-1-22 16:09

    ——检索方式

    Hibernate中提供了以下几种检索对象的方式:
        *   导航对象图检索方式
            根据已经加载额对象导航到其他对象。
            >   Customer customer = (Customer)session.get(Customer.class, 1)
                customer.getOrders(); // 得到客户的订单

        *   OID检索方式
            按照对象的OID来检索对象。
            >   get() / load()

        *   HQL检索方式
            使用面向对象的HQL查询语言。
            >   Query query = session.createQuery(String HQL)

        *   QBC检索方式
            使用QBC API来检索对象,这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口。
            >   Criteria criteria = session.createCriteria(Customer.class)

        *   本地SQL检索方式
            使用本地数据库的SQL查询语句。
            >   SQLQuery quer = session.createSQLQuery(String sql)

    ——HQL

    1、HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用最广泛的一种检索方式,它有如下功能:
        *   在查询语句中设定各种查询条件
        *   支持投影查询,即仅检索出对象的部分属性
        *   支持分页查询
        *   支持连接(多表)查询
        *   支持分组查询,允许使用HAVING和GROUP BY关键字
        *   提供内置函数,如SUM(),MIN(),MAX()
        *   能够调用用户自定义的SQL函数或标准的SQL函数
        *   支持子查询
        *   支持动态绑定参数

    2、HQL检索方式包括以下步骤
        *   通过Session的createQuery()方法创建一个Query对象,它包括一个HQL查询语句,HQL查询语句中可以包含命名参数。
        *   动态绑定参数
        *   调用Query的list()方法执行查询语句,该方法返回java.util.List类型的查询结果,在List集合中存放了复合查询条件的持久化对象。

    3、Query接口支持方法调用链编程风格,它的setXxx()方法返回自身实例,而不是void类型

    4、HQL和SQL的区别
        1)HQL查询语句是面向对象的,Hibernate负责解析HQL查询语句,然后根据对象 - 关系映射文件中的映射信息,把HQL查询语句翻译成相应的SQL语句,HQL查询语句中的主体是域模型中的类及类的属性。
        2)SQL查询语句是与关系型数据库绑定在一起的,SQL查询语句中的主体是数据库表及表的字段。

    示例代码:
        1)使用HQL查询所有数据
            // 使用HQL查询全部客户信息

            // Query query = session.createQuery("from Customer");
            // List<Customer> list = query.list();
            // print(list);


        2)使用别名进行查询
            // 使用别名查询

            // List<Customer> list = session.createQuery("from Customer as c").list();
            // print(list);
     
            // 使用别名查询:条件查询,as关键字可以省略
            // 不支持select * from 表的语法,但是可以使用:select 别名 from 表 as 别名
            Query query = session.createQuery("from Customer as c where c.cname = ?");
            // query.setString(0, "张三");
            // 除了setString(),也可以setParameter()
            query.setParameter(0, "张三");
            List<Customer> list = query.list();
            print(list);

        3)多态查询
            会将配置文件中实现了指定类的全部子类都进行查询。
            Query query = session.createQuery("from java.lang.Object");
            print(query.list());

        4)对查询结果进行排序
            List<Customer> list = session.createQuery("from Customer as c order by c.id desc").list();
            print(list); 

        5)分页查询
            // 使用HQL进行分页查询
            Query query = session.createQuery("from Order");
            query.setFirstResult(0);
            query.setMaxResults(11);
            List<Order> list = query.list();
            print(list);

        6)查询单个记录
            // 使用HQL查询单个记录
            Query query = session.createQuery("from Customer where cname = ?");
            query.setString(0, "李四");
            // 当结果超过1条时,uniqueResult()方法会报错
            Customer customer = (Customer) query.uniqueResult();
            System.out.println(customer);

        7)投影查询
            /*
             * 只查询客户的名称
             * 如果只查询一个属性,返回的是String
             * 如果查询多个属性,返回的是一个Object数组
             */
            // Query query = session.createQuery("select c.cid, c.cname from Customer as c");
            // 查询一个属性时,返回字符串
            // List<String> = query.list();
            // 查询多个属性时返回数组
            // List<Object[]> list = query.list();
            /*
             * 将查询记录封装到对象中
             * 为实体类提供一个对应参数的构造方法
             * public Customer(Integer cid, String cname){ ... } 
             */
            Query query = session.createQuery("select new Customer(cid, cname) from Customer");
            List<Customer> list = query.list();
            print(list);

        8)绑定参数,进行条件查询
            // 使用?方式绑定参数
            Query query = session.createQuery("from Customer where cname = ?");
            query.setParameter(0, "李四");
            List<Customer> list = query.list();
            print(list);

            // 多个参数
            Query query = session.createQuery("from Customer where cname = ? and cid = ?");
            query.setParameter(0, "李四");
            query.setParameter(1, 2);
            List<Customer> list = query.list();
            print(list);

            // 使用名称方式绑定参数
            Query query = session.createQuery("from Customer where cname = :name and cid = :id");
            query.setParameter("name", "李四");
            query.setParameter("id", 2);
            List<Customer> list = query.list();
            print(list);

            // 绑定实体参数
            Customer customer = new Customer();
            customer.setCid(1);
            Query query = session.createQuery("from Order as o where o.customer = ?");
            query.setEntity(0, customer);
            List<Order> list = query.list();
            print(list);

        9)模糊查询
            // 使用HQL进行模糊查询
            Query query = session.createQuery("from Customer where cname like ?");
            query.setParameter(0, "李%");
            List<Customer> list = query.list();
            print(list);

        10)聚合函数
            // 使用聚合函数查询
            Query query = session.createQuery("select count(*) from Order");
            List<Order> list = query.list();
            print(list); 


    ——QBC

    QBC运算符:

        图片


    示例代码:
        1)使用QBC查询所有数据
            // 使用QBC的方式查询所有客户信息

            // Criteria criteria = session.createCriteria(Customer.class);
            // print(criteria.list());


        2)对查询结果进行排序

            Criteria criteria = session.createCriteria(Customer.class).addOrder(org.hibernate.criterion.Order.desc("id"));
            print(criteria.list());

        3)分页查询
            // 使用QBC进行分页查询
            Criteria criteria = session.createCriteria(Order.class);
            criteria.setFirstResult(0);
            criteria.setMaxResults(11);
            List<Order> list = criteria.list();
            print(list);

        4)查询单个记录
            // 使用QBC查询单个记录
            Criteria criteria = session.createCriteria(Customer.class);
            // 设置条件
            criteria.add(Restrictions.eq("cname", "李四"));
            // 只查询第一条记录
            criteria.setMaxResults(1);
            Customer customer = (Customer) criteria.uniqueResult();
            System.out.println(customer);

        5)条件查询
            // 绑定一个参数
            Criteria criteria = session.createCriteria(Customer.class);
            criteria.add(Restrictions.eq("cname", "李四"));
            // 绑定多个参数
            criteria.add(Restrictions.eq("cid", "2")); 
            List<Customer> list = criteria.list();
            print(list);

        6)模糊查询
            // 使用QBC进行模糊查询
            Criteria criteria = session.createCriteria(Customer.class);
            criteria.add(Restrictions.like("cname", "李%"));
            List<Customer> list = criteria.list();
            print(list);


    ——SQL

    示例代码:
        1)使用SQL查询所有数据

            // 使用SQL语句查询全部客户信息
            SQLQuery query = session.createSQLQuery("select * from Customer"); 
            List<Object[]> list = query.list();
            printArr(list);
     
        2)使用SQL查询所有数据,并将数据封装到实体对象中
            // 使用SQL查询全部客户信息,并将结果记录封装到实体对象中
            SQLQuery query = session.createSQLQuery("select * from Customer");
            List<Customer> list = query.addEntity(Customer.class).list();
            print(list);



    ——多表查询

    1、普通多表查询
        1)交叉连接
            select * from A,B;
            得到的是笛卡尔积。

        2)内连接
            查询的是两个表的交集
                select * from A inner join B on A.字段 = B.字段;

            隐式内连接:
                select * from A, B where A.字段 = B.字段

        3)外连接
            左外连接
                select * from A left outer join B on A.字段 = B.字段
            右外连接
                select * from A right outer join B on A.字段 = B.字段

    2、在HQL中的多表查询
        1)交叉连接
        2)内连接
        3)隐式内连接
        4)迫切内连接
        5)左外连接
        6)迫切左外连接
        7)右外连接

    3、示例代码
        1)内连接
            /*

             * HQL内连接查询
             * 查询的是两个表的交集部分
             */
            Query query = session.createQuery("from Customer as c inner join c.orders");
            List list = query.list();
            printArr(list);


        2)迫切内连接
            // 迫切内连接,使用一个关键字fetch

            // 如果使用from Customer as c inner join fetch c.orders,则会出现重复的Customer
            // 可以使用distinct关键字去除重复的Customer:select distinct c 
            Query query = session.createQuery("select distinct c from Customer as c  inner join fetch c.orders");
            List list = query.list();
            print(list);


    4、左外连接与迫切左外连接的用法与内连接、迫切内连接相同

    5、HQL的内连接与迫切内连接的区别:
        内连接查询:
            将数据封装到List<Object[]>中。
        迫切内连接:
            将数据封装到一个List<Customer>中,但是迫切内连接会得到重复的记录,需要使用distinct去重。

    ——离线条件查询

    现在有这么一个表单,可以根据不同的查询条件进行不同的查询操作,但是DAO层无法获取Web层的对象,可以使用离线对象进行操作。

    传统方式:
        UserService user = new UserService();
        user.findByCondition(username, sex, edu, tel);
        这样做的局限性在于无法修改上传的内容,不方便扩展。

    离线方式:
        获得一个离线的Criteria,在Web层将Criteria对象的条件设置好。
            criteria.add(Restrictions.eq("name", "张三"));
            criteria.add(Restrictions.eq("sex", "男"));

        然后在Web层调用service方法传入Criteria对象,在DAO层获取可执行的离线Criteria对象。

    示例代码:

        /*
         * 离线条件查询
         */
        public void fun15(){
            Session session = HibernateUtils.openSession();
            Transaction tx = session.beginTransaction();
     
            // 在Web层创建离线对象
            DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
            // 设置参数
            criteria.add(Restrictions.eq("cname", "李四"));
            criteria.add(Restrictions.eq("cid", 2));

     
     
            // 在DAO层获得可执行的Criteria对象
            Criteria criteria2 = criteria.getExecutableCriteria(session);
            List<Customer> list = criteria2.list();
     
            print(list);
     
            tx.commit();
            session.close();
        }


    ——总结

    1、对象导航方式
        *   可以通过一个对象获得到关联对象。

    2、根据OID进行检索
        *   get()
        *   load();

    3、HQL
        *   session.createQuery(String hql);
        *   简单查询:from Customer
        *   排序:from Customer c order by c.cid desc;
        *   条件查询:位置绑定参数(?),名称绑定参数(:name)
        *   分页查询:query.setFirstResult(int from); query.setMaxResult(int max)
        *   聚合函数:select count(*) from Customer group by cid;
        *   多态查询:from java.lang.Object
        *   投影查询:select cid, cname from Customer
        *   构造方法将查询结果封装成对象:select new Customer(cid, cname) from Customer
        *   多表查询
            >   交叉连接
            >   内连接
            >   迫切内连接
            >   左外连接
            >   迫切左外连接
        *   命名查询

    4、QBC
        *   session.createCriteria(Class class);
        *   简单查询
        *   排序查询
        *   条件查询:criteria.add(Restrictions(name, value));
        *   分页查询
        *   离线条件查询

    5、SQL
        *   session.createSQLQuery(String sql);

        图片

  • 相关阅读:
    Python 命令详解
    redhat 6 / centos 6 搭建Django环境
    Linux rsync 命令详解
    Python 文件处理
    [网络流24题]最长不下降子序列问题
    [网络流24题]圆桌问题
    BZOJ 4675(点分治)
    LOJ 2183 / SDOI2015 序列统计 (DP+矩阵快速幂)
    BZOJ 3931 (网络流+最短路)
    [网络流24题]魔术球问题
  • 原文地址:https://www.cnblogs.com/wwwwyc/p/6375465.html
Copyright © 2011-2022 走看看