Hibernate框架的学习--第四天

时间:2022-12-05 14:21:15

一、 Hibernate查询高级

    1. 查询总结

        1.oid查询-get

       2.对象属性导航查询

       3.HQL

       4.Criteria

       5.原生SQL

   2. 查询-HQL语法

        1)基础语法      

   /**
     * 基本语法
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql1 = "from com.java.domain.Customer"; //完整写法  
        String hql2 = "from Customer"; //简单写法
        //2>创建查询的对象
        Query query = session.createQuery(hql2);
        //3>执行查询操作
        List<Customer> list = query.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  2)排序     

  /**
     * 排序查询
     * 
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql1 = "from Customer order by cust_id desc"; //降序查询
        String hql2 = "from Customer order by cust_id asc"; //升序查询
        //2>创建查询的对象
        Query query = session.createQuery(hql2);
        //3>执行查询操作
        List<Customer> list = query.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  3)条件查询

          ?占位符和命名占位符 

  /**
     * 条件查询
     * ?占位符
     * 命名占位符
     */
    @Test
    public void fun3() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql1 = "from Customer where cust_id=?"; //简单写法
        String hql2 = "from Customer where cust_id=:cust_id";
        //2>创建查询的对象
        Query query = session.createQuery(hql2);
        
        //设置查询的参数
        //query.setParameter(0, 1l);
        query.setParameter("cust_id", 1l);
        //3>执行查询操作
        List<Customer> list = query.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  4)分页查询        

      limit ?,?
     query.setFirstResult(2);
     query.setMaxResults(2); 

    /**
     * 分页查询
     * limit ?,?
     *    query.setFirstResult(2);
     *    query.setMaxResults(2);
     */
    @Test
    public void fun4() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql = "from Customer"; //简单写法
        //2>创建查询的对象
        Query query = session.createQuery(hql);
        
        //limit ?,?
        query.setFirstResult(2);
        query.setMaxResults(2);
        
        //3>执行查询操作
        List<Customer> list = query.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  5)统计检索(聚合函数)

  /**
     * 统计检索(聚合函数)
     *    
     */
    @Test
    public void fun5() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql1 = "select count(*) from Customer"; //简单写法
        String hql2 = "select sum(cust_id) from Customer"; //简单写法
        String hql3 = "select avg(cust_id) from Customer"; //简单写法
        String hql4 = "select min(cust_id) from Customer"; //简单写法
        String hql5 = "select max(cust_id) from Customer"; //简单写法
        //2>创建查询的对象
        Query query = session.createQuery(hql5);
        
        //3>执行查询操作
        Number result = (Number) query.uniqueResult();
        System.out.println(result);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  6)投影查询

  /**
     * 投影查询
     *    
     */
    @Test
    public void fun6() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql1 = "select cust_id from Customer"; //简单写法
        String hql2 = "select cust_id,cust_name from Customer"; //简单写法
        String hql3 = "select new Customer(cust_id, cust_name) from Customer"; //简单写法
        //2>创建查询的对象
        Query query = session.createQuery(hql3);
        
        //3>执行查询操作
        List list = query.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  7)多表查询

        Hibernate框架的学习--第四天

     1) 原生SQL

        交叉连接-笛卡尔积(避免)
       select * from A,B
       内连接
            |-隐式内连接
    select * from A,B where B.aid=A.aid
       |-显式内连接
          select * from A inner join B on B.aid=A.aid
  外连接
    |-左外连接
    select * from A left [outer] B on B.aid=A.aid
       |-右外连接
    select * from A right [outer] B on B.aid=A.aid

    2)HQL的多表查询

   内连接(迫切)
   外连接
      |-左外(迫切)
      |-右外(迫切)

    3)HQL多表查询的案例

public class Demo02 {
    /**
     * 内连接
     * 将连接两端的对象分别返回放入数组
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql = "from Customer c inner join c.linkMens"; //完整写法  
        //2>创建查询的对象
        Query query = session.createQuery(hql);
        //3>执行查询操作
        List<String[]> list = query.list();
        for(Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 内连接迫切
     * 将两端的对象封装成一个对象返回
     * from Customer c inner join c.linkMens
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql = "from Customer c inner join fetch c.linkMens"; //完整写法  
        //2>创建查询的对象
        Query query = session.createQuery(hql);
        //3>执行查询操作
        List<Customer> list = query.list();
        for(Customer c : list) {
            System.out.println(c);
        }
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 左外连接
     * 将连接两端的对象分别返回并放到数组中
     * from Customer c left join c.linkMens
     */
    @Test
    public void fun3() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql = "from Customer c left join c.linkMens"; //完整写法  
        //2>创建查询的对象
        Query query = session.createQuery(hql);
        //3>执行查询操作
        List<Object[]> list = query.list();
        for(Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    
    /**
     * 右外连接
     * 将连接两端的对象分别返回并放到数组中
     * from Customer c right join c.linkMens
     */
    @Test
    public void fun4() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>定义hql语句
        String hql = "from Customer c right join c.linkMens"; //完整写法  
        //2>创建查询的对象
        Query query = session.createQuery(hql);
        //3>执行查询操作
        List<Object[]> list = query.list();
        for(Object[] obj : list) {
            System.out.println(Arrays.toString(obj));
        }
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }  
}

  3. 查询-Criteria语法

   1)基本知识

           QBC(Query By Criteria)是hibernate提高的另一种检索对象的方式,它主要由Criteria接口Criterion接口和Expression类组成。Criteria接口是Hibernate API中的一个查询接口,它需由session进行创建。Criterion是Criteria的查询条件,在Criteria中提供了add(Criterion criterion)方法来添加查询条件。使用QBC检索对象的示例代码如下:     

    //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        //2>添加查询条件
        //criteria.add(Restrictions.idEq(1l));
        criteria.add(Restrictions.eq("cust_id", 1l));
        //3>执行查询
        List<Customer> list = criteria.list();

  QBC检索是使用Restrictions对象编写查询条件的,在Restrictions类中提供了大量的静态方法来创建查询条件,其常用的方法如表所示:                  

          Hibernate框架的学习--第四天

  2)基本查询

    /**
     * 基本语法
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(LinkMan.class);
        
        //2>执行查询
        List<LinkMan> list = criteria.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  2)条件查询

  /**
     * 条件查询
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        //2>添加查询条件
        //criteria.add(Restrictions.idEq(1l));
        criteria.add(Restrictions.eq("cust_id", 1l));
        //3>执行查询
        List<Customer> list = criteria.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  3)分页查询

/**
     * 分页查询
     * limit ?,?
     * criteria.setFirstResult(0);
     * criteria.setMaxResults(2);
     */
    @Test
    public void fun3() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        //2>设置分页查询的参数 limit ?,?
        criteria.setFirstResult(0);
        criteria.setMaxResults(2);
        
        //3>执行查询
        List<Customer> list = criteria.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }

  4)排序查询

/**
     * 排序查询
     *  criteria.addOrder(Order.asc("cust_id")); //升序查询
     *    criteria.addOrder(Order.desc("cust_id")); //降序查询
     */
    @Test
    public void fun4() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        //2>添加排序条件
        //criteria.addOrder(Order.asc("cust_id")); //升序查询
        criteria.addOrder(Order.desc("cust_id")); //降序查询
        
        //3>执行查询
        List<Customer> list = criteria.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
    }

  5)统计查询

/**
     * 统计查询
     * 总记录数 
     * criteria.setProjection(Projections.rowCount());
     */
    @Test
    public void fun5() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        //1>创建ceriteria对象
        Criteria criteria = session.createCriteria(Customer.class);
        
        //2>设置查询目标  总记录数
        criteria.setProjection(Projections.rowCount());
        
        //3>执行查询
        List<Customer> list = criteria.list();
        System.out.println(list);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
    }

  4. 查询优化

 1)类级别查询

        get方法:没有任何策略.调用即立即查询数据库加载数据.

       load方法: 应用类级别的加载策略       

  懒加载 延迟加载
   load()方法(默认):是在执行时,不会发送任何sql语句,通过动态代理返回一个对象,
  在对象使用的时候,才执行查询

   延迟加载:仅仅获得没有使用,不会查询。在使用时,才进行查询
   是否对类延迟加载可以通过在class元素上配置lazy属性
   lazy(默认):true 加载时不查询,使用时才查询
   lazy:false load方法与get方法没有任何区别 加载时立即查询

  为了提高效率建议使用懒加载

public class Demo {
    /**
     * get()方法:立即加载。执行方法时立即发送sql语句查询结果
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.get(Customer.class, 2l);
        System.out.println(c);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    
    /**
     * load()方法(默认):是在执行时,不会发送任何sql语句,通过动态代理返回一个对象,
     *                     在对象使用的时候,才执行查询
     * 延迟加载:仅仅获得没有使用,不会查询。在使用时,才进行查询
     * 是否对类延迟加载可以通过在class元素上配置lazy属性
     *  lazy(默认):true   加载时不查询,使用时才查询
     *  lazy:false  加载时立即查询
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.load(Customer.class, 2l);
        System.out.println(c);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
    }
    
    
}

  2)关联级别查询

          1. 集合策略

       lazy属性:决定是否延迟加载
        true(默认值):延迟加载,懒加载
          false:立即加载
        extra:及其懒惰
       fetch属性:决定加载策略,使用什么类型的sql语句加载集合数据
                select(默认值):单表查询加载
           join:使用多表查询加载集合
           subselect:使用子查询加载查询集合           

/**
 * 
 *  关联级别  延迟加载
 *  集合级别的关联
 * @author vanguard
 *
 */
public class Demo {
    /**
     * 集合级别的关联
     * fetch:select  单表查询
     * lazy:true 延迟加载  使用时才加载集合数据
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.get(Customer.class, 2l);
        
        Set<LinkMan> linkMens = c.getLinkMens(); //关联级别
        
        System.out.println(linkMens);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:select  单表查询
     * lazy:false 立即加载数据
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.get(Customer.class, 2l);
        
        Set<LinkMan> linkMens = c.getLinkMens(); //关联级别
        
        System.out.println(linkMens);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:select  单表查询
     * lazy:extra 极其懒惰
     * 与懒加载效果基本一致. 如果只获得集合的size.只查询集合的size(count语句)
     */
    @Test
    public void fun3() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.get(Customer.class, 2l);
        
        Set<LinkMan> linkMens = c.getLinkMens(); //关联级别
        
        System.out.println(linkMens.size());
        
        System.out.println(linkMens);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:join 使用多表查询加载集合数据
     * lazy:true|false|extra失效  立即加载
     */
    @Test
    public void fun4() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        Customer c = session.get(Customer.class, 2l);
        
        Set<LinkMan> linkMens = c.getLinkMens(); //关联级别
        
        System.out.println(linkMens.size());
        
        System.out.println(linkMens);
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:subselect 使用子查询加载集合数据
     * lazy:true  延迟加载
     */
    @Test
    public void fun5() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        String hql = "from Customer";
        
        Query query = session.createQuery(hql);
        
        List<Customer> list = query.list();
        
        for(Customer c : list) {
            System.out.println(c.getLinkMens());
        }
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:subselect 使用子查询加载集合数据
     * lazy:false  立即加载加载
     */
    @Test
    public void fun6() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        String hql = "from Customer";
        
        Query query = session.createQuery(hql);
        
        List<Customer> list = query.list();
        
        for(Customer c : list) {
            System.out.println(c.getLinkMens());
        }
           
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 集合级别的关联
     * fetch:subselect 使用子查询加载集合数据
     * lazy:extra  极其懒惰加载
     */
    @Test
    public void fun7() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        String hql = "from Customer";
        
        Query query = session.createQuery(hql);
        
        List<Customer> list = query.list();
        
        for(Customer c : list) {
            System.out.println(c.getLinkMens().size());
            System.out.println(c.getLinkMens());
        }
        
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
}

    2. 关联属性策略     

     fetch属性 决定加载的sql语句
      select:使用单表查询
      join:使用多表查询
     lazy:决定加载时机
      false:立即加载
      proxy:有customer的类级别加载策略决定

         

/**
 * 
 *  关联级别  延迟加载
 *  属性策略
 * @author vanguard
 *
 */
public class Demo02 {
    /**
     * 
     * fetch:select  单表查询
     * lazy:proxy 
     *   Customer--true 
     */
    @Test
    public void fun1() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);
        
        Customer customer = linkMan.getCustomer();
        
        System.out.println(customer);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 
     * fetch:select  单表查询
     * lazy:proxy 
     *   Customer--false 立即加载 
     */
    @Test
    public void fun2() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);
        
        Customer customer = linkMan.getCustomer();
        
        System.out.println(customer);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    /**
     * 
     * fetch:join  多表查询
     * lazy:proxy 失效  都是立即加载
     */
    @Test
    public void fun3() {
        //1. 获得session
        Session session = HibernateUtils.getSession();
        //2. 开启事务并获得操作事务的对象
        Transaction tx = session.beginTransaction();
        //3. 执行操作
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);
        
        Customer customer = linkMan.getCustomer();
        
        System.out.println(customer);
        
        //4. 提交事务并释放资源
        tx.commit();
        session.close();
        
    }
    
}

   结论:为了提高效率.fetch的选择上应选择select. lazy的取值应选择 true. 全部使用默认值.

     4. no-session问题解决:

       扩大session的作用域

         Hibernate框架的学习--第四天

   3)批量抓取

           betch-size:值是抓取集合的数量

          抓取客户的集合时,一次抓取集合客户的联系人