zoukankan      html  css  js  c++  java
  • Hibernate 的查询

    1. Hibernate 框架的查询方式

    • 唯一标识OID的检索方式: session.get(对象.class, OID)
    • 对象导航的方式;
    • HQL 检索方式;
    • QBC 检索方式;
    • SQL 检索方式

    2. HQL 检索方式

    2.1 HQL 与 SQL 的关系

    • HQL: Hibernate Query Language; 使用的是 Query 接口;
    • HQL 查询语句是面向对象的. Hibernate 负责解析 HQL 查询语句,然后根据对象-关系映射文件中的映射信息,把 HQL
      查询语句翻译成相应的 SQL 语句;
    • HQL 查询语句中的主体是域模型中的类及类的属性;
    • SQL 查询语句中的主体是数据库表及表的字段;

    2.2 HQL 查询所有

    // 查询所有客户
        // 第一种方式:
        // 创建 HQL 的查询接口(即 Query 接口)
        Query query = session.createQuery("from Customer");
        List<Customer> list = query.list();
    
        // 第二种方式: 方法链
        List<Customer> list = session.createQuery("from Customer").list();
    
        // 第三种方式: 使用别名的方式
        List<Customer> list = session.createQuery("from Customer c").list();
        List<Customer> list = session.createQuery("select c from Customer c").list();
    

    2.3 HQL 条件查询

    // 第一种方式:
        Query query = session.createQuery("from Customer where name=?");
        query.setString(0,"张三");  // 给第一个问号赋值
        List<Customer> list = query.list();
    
    // 第二种方式:
        Query query = session.createQuery("from Customer where name= :aaa and age= :bbb");
        query.setString("aaa","张三");
        query.setInteger("bbb",39);
        List<Customer> list = query.list();
    
    // 第三种方式:
        Query query = session.createQuery("from Customer where name=?");
        query.setParameter(0,"张三");  // "setParameter" 不用考虑参数的具体类型;
    

    2.4 HQL 排序查询

    // 升序
        session.createQuery("from Customer order by cust_id").list();
    
    // 降序
        session.createQuery("from Customer order by cust_id desc").list();
    

    2.5 HQL 分页查询

    // Hibernate 框架提供了关于分页的两个方法
        // setFirstResult(a)  : 从哪条记录开始,如果查询是从第一条记录开始, 值是 0;
        // setMaxResults(b) : 每页查询的记录条数;
    
        List<LinkMan> list = session.creatQuery("from Customer").setFirstResult(0)
                                                                .setMaxResults(10).list();
    

    2.6 HQL 投影查询

    • 投影查询就是想查询某一字段或某几个字段的值;
    // 需求: 查询多个字段
    // 第一种方式: 返回的是由这几个字段组成的数组
        List<Object[]> list = session.createQuery("select c.cust_name,c.cust_level from Customer c").list();
        for(Object[] objects : list){
            System.out.println(Arrays.toString(objects));
        }
    
    
    // 第二种方式: 返回只有这几个字段组成的对象
        // 1. 需要先在持久化类中提供对应字段的有参构造方法;
        // 2. 通过 new 将多个字段封装到对象中, 进行查询;
    
        public class Customer{
            private String cust_name;
            private Integer cust_age;
            private String cust_level;
            ...
    
            // 有参构造方法
            public Customer(String cust_name, String cust_level){
                this.cust_name = cust_name;
                this.cust_level = cust_level;
            }
    
            // 保留空的构造方法
            public Customer(){
                super();
            }
    
            .....get 和 set 方法
    
        }
    
        List<Customer> list = session.createQuery("select 
                new Customer(c.cust_name, c.cust_level)  from Customer c").list();
        for(Customer customer : list){
            System.out.println(customer);
        }
    

    2.7 HQL 聚合函数

    • count()
    • sum()
    • avg()
    • min()
    • max()
    // 1. 获取总的记录数
        // List<Number> list = session.createQuery("select count(*) from Customer").list();
        List<Number> list = session.createQuery("select count(c) from Customer c").list();
        Long count = list.get(0).longValue();
        System.out.println(count);
    
    // 2. 获取某一列数据的和
     List<Number> list = session.createQuery("select sum(c.cust_id) from Customer c").list();
        Long count = list.get(0).longValue();
        System.out.println(count);
    

    3. QBC 检索方式

    3.1 QBC 概述

    • QBC,Query By Criteria, 使用 Criteria 接口;
    • 完全面向对象;
    • 非常适合做条件查询;

    3.2 QBC 查询所有

    // 查询所有记录
        Criteria criteria = session.createCriteria(Customer.class);
        List<Customer> list = criteria.list();
    

    3.3 排序查询

    • 使用 addOrder() 方法来设置参数; org.hibernate.criterion.Order
        Criteria criteria = session.createCriteria(Customer.class);
        // 设置为降序
        criteria.addOrder(Order.desc("cust_id"));
        List<Customer> list = criteria.list();
    

    3.4 分页查询

    • setFirstResult()
    • setMaxResults()
        Criteria criteria = session.createCriteria(Customer.class);
        // 设置为降序
        criteria.addOrder(Order.desc("cust_id"));
    
        // 设置分页的方法
        criteria.setFirstResult(0);
        criteria.setMaxResults(10);
    
        List<Customer> list = criteria.list();
    

    3.5 QBC 条件查询

    • 条件查询使用 Criteria 接口的 add 方法,用来传入条件;
    • Criterion 接口,表示查询的条件;
    • Restrictions 类是 Hibernate 框架提供的工具类,不是 Criterion 接口的实现类;用来设置查询条件;
    • Restrictions 中常用方法:
      • eq(等于), gt(大于), lt(小于)
      • ge(大于等于), le(小于等于)
      • between: 在...之间, 头和尾都包含;
      • like: 模糊查询;
      • in: 范围;
      • and: 并且;
      • or: 或者;
      • isNull: 判断值是否为空;
      • isEmpty: 判断关联的集合是否为空;
    // 查询姓名叫"张三"的客户
        Criteria criteria = session.createCriteria(Customer.class);
    
        // 使用 Restrictions 传入条件
        criteria.add(Restrictions.eq("name","张三"));
        List<Customer> list = criteria.list();
    
    // 查询姓名中包含"小"的客户(模糊查询)
        Criteria criteria = session.createCriteria(Customer.class);
        criteria.add(Restrictions.like("name","%小%"));
        List<Customer> list = criteria.list();
    
        // in 方法
        // Restrictions.in(String propertyName, Collection values); // 集合
        // Restrictions.in(String propertyName, Object[] values);  // 数组
    
        List<Long> params = new ArrayList<Long>();
        params.add(1L);
        params.add(2L);
        params.add(7L);
    
        criteria.add(Restrictions.in("cust_id",params));
    
        // or 方法, 性别为女,或者 cust_id 大于 3
        criteria.add(Restrictions.or(Restrictions.eq("cust_gender","女"),Restrictions.gt("cust_id",3L)));
    

    3.6 QBC 聚合函数查询

    • Projections 是 Hibernate 框架的工具类,用来设置聚合函数查询; org.hibernate.criterion包下
    • 需要使用 criteria.setProjection() 来添加条件;

        Criteria criteria = session.createCriteria(Customer.class);
        // 设置聚合函数
        criteria.setProjection(Projections.rowCount());
    
        List<Number> list = criteria.list();
        Long count = list.get(0).longValue();
    
    // 注意问题
        pubic void fun(){
            Session session = HibernateUtils.getCurrentSession();
            Transaction tr = session.beginTransaction();
    
            // 创建 QBC 查询接口
            Criteria criteria = session.createCriteria(Customer.class);
            // 设置聚合函数
            criteria.setProjection(Projections.count("cust_id"));
            List<Number> list = criteria.list();
            Long count = list.get(0).longValue();
    
            // 因为此时的查询语句, 相当于 select count(cust_id) from 表
            // 如果想继续查询所有客户,需要 setProjection(null);
            criteria.setProjection(null);
    
            // 继续查询所有客户
            List<Customer> customers = criteria.list();
            for(Customer customer : customers){
                System.out.println(customer);
            }
        }
    

    4. 离线条件查询

    • 离线条件查询使用的是 DetachedCriteria 接口进行查询;
    • 离线条件查询对象在创建的时候,不需要使用 session 对象, 只是在查询的时候,使用 session 对象;
    • 可以在 WEB 层创建离线条件查询对象;

        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
    
        // 创建离线条件查询对象
        DetachedCriteria criteria = DetachedCriteria.forClass(Customer.class);
    
        // 设置查询条件
        criteria.add(Restrictions.eq("cust_gender","男"));
        // 查询数据, 需要使用 session
        List<Customer> list = criteria.getExecutableCriteria(session).list();
        for(Customer customer : list){
            System.out.println(customer);   
        }
    
        tr.commit();
    

    5. SQL 查询方式(了解)

        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
    
        SQLQuery sqlQuery = session.createSQLQuery("select * from cust_customer where cust_gender = ?");
        sqlQuery.setParameter(0,"男");
    
        // 将返回结果(是List<Object[]> 类型), 封装到对象中
        sqlQuery.addEntity(Customer.class);
        List<Customer> list = sqlQuery.list();
    
        for(Customer customer : list){
            System.out.println(customer);
        }
    
        tr.commit();
    

    6. HQL 多表查询

    6.1 SQL 的多表查询

    // 内连接查询
        // 显示内连接
        select * from customer c inner join orders o on c.cid = o.cno;
        // 隐式内连接
        select * from customer c, orders o where c.cid = o.cno;
    
    // 外连接
        // 左外连接
        select * from customer c left outer join orders o on c.cid = o.cno;
        // 右外连接
        select * from customer c right outer join orders o on c.cid = o.cno;
    

    6.2 HQL 的多表查询

    • 非迫切连接: 返回的结果是 Object[];
    • 迫切连接: 返回的结果是对象,
    // 使用内连接查询,默认返回的是 Object 数组
        Session session = HibernateUtils.getCurrentSession();
        Transaction tr = session.beginTransaction();
    
        List<Object[]> list = session.createQuery("from Customer c inner join c.linkmans").list();
        for(Object[] objects : list){
            System.out.println(Arrays.toString(objects));
        }
    
    // 使用 fetch 关键字, 会把返回结果封装到对象中
    // fetch 迫切连接
        List<Customer> list = session.createQuery("from Customer c inner join fetch c.linkmans").list();
        for(Customer customer : list){
            System.out.println(customer);   
        }
    
    // 解决数据重复的问题, 因为 Customer 对象中存在 Set<Linkman> linkmans 集合
    // 所以返回的结果, 一个联系人对应一个客户.
    // 需要的结果: 一个客户中存在n个联系人. 自己手动 new Set 集合
        List<Customer> list = session.createQuery("from Customer c inner join fetch c.linkmans").list();
        Set<Customer> set = new HashSet<Customer>(list);
    
        for(Customer customer : set){
            System.out.println(customer);
        }
    
    
    // 迫切左外连接
        List<Customer> list = session.createQuery("from Customer c left join fetch c.linkmans").list();
    

    7. HQL 框架之延迟加载

    1. 延迟加载先获取到代理对象,当真正使用到该对象中的属性的时候,才会发送 SQL 语句, 是 Hibernate 框架提升性能的方式;
    2. 类级别的延迟加载
      • session 对象的 load() 方法就是延迟加载;
      • Customer c = session.load(Customer.class, 1L)
        没有发送 SQL 语句, 当使用该对象的属性时,才发送 SQL 语句
      • 使类级别的延迟加载失效(两种方法)
        • <class> 标签上配置 lazy="false";
        • Hibernate.initialize(Object proxy);
    3. 关联级别的延迟加载
      • 查询某个客户下的所有联系人, 默认是延迟加载;

    8. Hibernate 框架关联级别的查询优化策略

    8.1 查询策略

    • 使用 Hibernate 框架查询一个对象的时候,查询其关联对象,应该如何查询. 是 Hibernate 框架的一种优化手段;

    8.2 Hibernate 框架的查询策略解决的问题

    1. 查询的时机
      • lazy属性解决查询的时机问题,表示是否需要延迟加载;
    2. 查询的语句形式
      • fetch属性解决查询语句的格式问题;

    8.3 在 <set> 标签上使用 fetchlazy 属性

    1. fetch 的取值:
      • select: 默认值,发送基本select语句查询;
      • join: 连接查询,发送的是一条迫切左外连接! 配置了该属性,lazy属性就失效了;
      • subselect: 子查询,发送一条子查询,查询关联对象;
    2. lazy 的取值
      • true: 默认延迟;
      • false: 不延迟;
      • extra: 及其懒惰;
    3. 总结: 开发中, 基本上使用的都是默认值: fetch = select, lazy=true;

    8.4 在 <many-to-one> 标签上使用 fetchlazy 属性

    1. fetch 的取值
      • select: 默认值,发送基本select语句查询;
      • join: 发送迫切左外连接查询;
    2. lazy 的取值
      • false: 不采用延迟加载;
      • proxy: 默认值,代理;表示由另一端 <class> 上的 lazy 属性决定;

    参考资料

  • 相关阅读:
    hadoop再次集群搭建(3)-如何选择相应的hadoop版本
    48. Rotate Image
    352. Data Stream as Disjoint Interval
    163. Missing Ranges
    228. Summary Ranges
    147. Insertion Sort List
    324. Wiggle Sort II
    215. Kth Largest Element in an Array
    快速排序
    280. Wiggle Sort
  • 原文地址:https://www.cnblogs.com/linkworld/p/7704939.html
Copyright © 2011-2022 走看看