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 属性决定;

    参考资料

  • 相关阅读:
    vue 安装scss
    element-ui 弹出添加拖拽功能
    百度网盘SVIP不限速Mac破解版(亲测可用)
    cookie,localStorage和sessionStorage
    ES6中class的实现原理
    闭包的使用场景
    HTTPS原理以及流程
    DOMContentLoaded和load的区别
    js中的函数防抖与节流
    对vuex的理解
  • 原文地址:https://www.cnblogs.com/linkworld/p/7704939.html
Copyright © 2011-2022 走看看