Hibernate(四) - HQL_QBC查询详解--抓取策略优化机制

Hibernate 的查询方式

  在 Hibernate 中提供了很多种的查询的方式。Hibernate 共提供了五种查询方式。

1、Hibernate 的查询方式:OID 查询

  OID检索:Hibernate根据对象的OID(主键)进行检索。

  ① 使用 get 方法

Customer customer = session.get(Customer.class,1l);

  ② 使用 load 方法

Customer customer = session.load(Customer.class,1l);

2、Hibernate 的查询方式:对象导航检索

  对象导航检索:Hibernate根据一个已经查询到的对象,获得其关联的对象的一种查询方式。

LinkMan linkMan = session.get(LinkMan.class,1l);
Customer customer  = linkMan.getCustomer();

Customer customer = session.get(Customer.class,2l);
Set linkMans = customer.getLinkMans();

3、Hibernate 的查询方式:HQL 检索

  HQL查询:Hibernate Query Language,Hibernate的查询语言,是一种面向对象的方式的查询语言,语法类似SQL。通过session.createQuery(),用于接收一个HQL进行查询方式。

  在进行 HQL 查询之前,先做一些准备。首先,新建一个 Java 项目,在项目里面新建一个文件夹,命名为 lib,并将上一个项目用到的包复制过来,添加的构建路径中去 。把工具类和配置文件拷贝过来。

  ① 初始化数据

package com.itheima.hibernate.demo1;

import java.util.Arrays;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.domain.LinkMan;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * HQL的查询方式的测试类
 * 
 * @author jt
 *
 */
public class HibernateDemo1 {

    @Test
    /**
     * 初始化数据
     */
    public void demo1() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        // 创建一个客户
        Customer customer = new Customer();
        customer.setCust_name("李向文");

        for (int i = 1; i <= 10; i++) {
            LinkMan linkMan = new LinkMan();
            linkMan.setLkm_name("王东" + i);
            linkMan.setCustomer(customer);

            customer.getLinkMans().add(linkMan);

            session.save(linkMan);
        }
        session.save(customer);

        tx.commit();
    }

  3.1、HQL 的简单查询

    /**
     * HQL的简单查询
     */
    public void demo2() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        // 简单的查询
     // 返回一个 Query 的接口,而且支持链式写法
        Query query = session.createQuery("from Customer");
        List list = query.list();

        // sql中支持*号的写法:select * from cst_customer; 但是在HQL中不支持*号的写法。
        /*
         * Query query = session.createQuery("select * from Customer");// 报错
         * List list = query.list();
         */


        // 再打印的时候,会默认调用对象的 toString(),两边不要都 toString(),都设置的话,其实就是一个死循环 
        // 为什么呢?因为你客户里面有联系人的集合,它需要把联系人给打印了;联系人那边呢,又有客户;客户又有联系人...
        // 这样的话就是一个死循环,所以在 toString() 的时候,把集合先去掉;打印先不打印集合,只是单纯的去看客户的一些数据

        // 这里一定需要注意,除了客户的打印,像你 JSON 的转换,两边互相与对象的时候,JSON 一转换,它也是一个死循环。
        for (Customer customer : list) {
            System.out.println(customer);
        }
        tx.commit();
    }    

 

  需要注意的是“from customer”这里是一个对象,正常的写法应该是带包名的;但是在映射里面已经配置的包了,所以这个地方可以省略。一定要注意 ,这个地方是类名,而不是你的表名。

  3.2、HQL 的别名查询

    @Test
    /**
     * 别名查询
     */
    public void demo3() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        // 别名的查询
        /*
         * Query query = session.createQuery("from Customer c"); List
         * list = query.list();
         */

        // 支持.属性的写法,但是需要注意的是 ,这种方式得到的 list 里面放的就不是一个对象了
        Query query = session.createQuery("select c from Customer c");
        List list = query.list();

        for (Customer customer : list) {
            System.out.println(customer);
        }
        tx.commit();
    }

  3.3、HQL 的排序查询

  它跟 SQL 语句很类似的,所以再做排序查询的时候跟 SQ L也是很相似的。

  里面也可以使用 order by,后面跟的是类里面的属性名,默认情况下就是升序的。

    @Test
    /**
     * 排序查询
     */
    public void demo4() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        // 排序的查询
        // 默认情况
        // List list = session.createQuery("from Customer order by
        // cust_id").list();
        // 设置降序排序 升序使用asc 降序使用desc
        List list = session.createQuery("from Customer order by cust_id desc").list();

        for (Customer customer : list) {
            System.out.println(customer);
        }
        tx.commit();
    }

  3.4、HQL 的条件查询

  支持两种条件查询的方式,

    @Test
    /**
     * 条件查询
     */
    public void demo5() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        // 条件的查询
        // 一、按位置绑定:根据参数的位置进行绑定。
        // 一个条件
        /*
         * Query query = session.createQuery("from Customer where cust_name = ?"
         * ); query.setParameter(0, "李兵"); List list = query.list();
         */

        // 多个条件
        /*
         * Query query = session.createQuery(
         * "from Customer where cust_source = ? and cust_name like ?");
         * query.setParameter(0, "小广告"); query.setParameter(1, "李%");
         * List list = query.list();
         */

        // 二、按名称绑定,名称随便起
        Query query = session.createQuery("from Customer where cust_source = :aaa and cust_name like :bbb");
        // 设置参数:
        query.setParameter("aaa", "朋友推荐");
        query.setParameter("bbb", "李%");
        List list = query.list();

        for (Customer customer : list) {
            System.out.println(customer);
        }
        tx.commit();
    }

  3.5、HQL 的投影查询

  投影查询:查询对象的某个或某些属性。

    @Test
    /**
     * 投影查询
     */
    public void demo6() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        // 投影查询
        // 单个属性,封装的是对象
// 返回一个 list,但里面装的是一个字符串类型的值。Object 可以强转称字符串
/* * List list = session.createQuery( * "select c.cust_name from Customer c").list(); for (Object object : * list) { System.out.println(object); } */ // 多个属性,封装的是对象的数组
// list 集合里面放置的是一个 Object 数组,不同类型的值要想通用,只能放到一个数组之中
/* * List list = session.createQuery( * "select c.cust_name,c.cust_source from Customer c").list(); for * (Object[] objects : list) { * System.out.println(Arrays.toString(objects)); } */ // 查询多个属性,但是我想封装到对象中。构造方法方式的查询
// 对持久化类(客户类)提供构造方法,无参构造
List list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }

   3.6、HQL 的分页查询

  直接调用方法

    @Test
    /**
     * 分页查询
     */
    public void demo7() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        // 分页查询
        Query query = session.createQuery("from LinkMan");
        query.setFirstResult(20);
        query.setMaxResults(10);
        List list = query.list();

        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
        tx.commit();
    }

  3.7、HQL 的分组统计查询

    @Test
    /**
     * 分组统计查询
     */
    public void demo8() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();

        // 聚合函数的使用:count(),max(),min(),avg(),sum()
// 得到的是唯一结果,可以使用uniqueResult()
Object object = session.createQuery("select count(*) from Customer").uniqueResult(); System.out.println(object); // 分组统计:
// 可以在语句后面加条件,和SQL语句一样(HAVING)
List list = session.createQuery("select cust_source,count(*) from Customer group by cust_source") .list(); for (Object[] objects : list) { System.out.println(Arrays.toString(objects)); } tx.commit(); }

  HQL还有一些非常特殊的用法,例如继承方式的查询,就是from Object查询java.lang.Object,会把所有的持久化类的数据查询出来。

4、Hibernate 的查询方式:QBC 检索

 

  QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。连语句的的形式都看不到了,直接调用的是对象中的方法,来进行一些相应的设置。但并不是所有地方都可以使用 QBC 查询,有些地方是不支持的。

  4.1、

package com.itheima.hibernate.demo1;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.domain.LinkMan;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * QBC的查询
 * @author jt
 *
 */
public class HibernateDemo2 {

    @Test
    /**
     * 简单的查询
     */
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 获得Criteria的对象
        Criteria criteria = session.createCriteria(Customer.class);
        List list = criteria.list();
        
        for (Customer customer : list) {
            System.out.println(customer);
        }
        tx.commit();
    }  
}
 

  4.2、QBC 的排序查询

    @Test
    /**
     * 排序查询
     */
    public void demo2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 排序查询
        Criteria criteria = session.createCriteria(Customer.class);
// addOeder 添加排序 Order 是 HIbernate 提供的
// criteria.addOrder(Order.asc("cust_id")); // 升序 criteria.addOrder(Order.desc("cust_id")); // 降序 List list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }

  4.3、QBC 的分页查询

    @Test
    /**
     * 分页查询
     */
    public void demo3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 分页查询
        Criteria criteria = session.createCriteria(LinkMan.class);
        criteria.setFirstResult(10);
        criteria.setMaxResults(10);
        List list = criteria.list();
        
        for (LinkMan linkMan : list) {
            System.out.println(linkMan);
        }
        tx.commit();
    }
    

  4.4、QBC 的条件查询

    @Test
    /**
     * 条件查询
     */
    public void demo4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 条件查询
        Criteria criteria = session.createCriteria(Customer.class);
        // 设置条件:
        /**
         * =   eq
         * >   gt
         * >=  ge
         * <   lt
         * <=  le
         * <>  ne
         * like
         * in
         * and
         * or
         */
// (属性名,值)
// 默认多个条件是并列的,在 SQL 语句中通过 and 连接 criteria.add(Restrictions.eq(
"cust_source", "小广告"));
// or 连接
// criteria.add(Restrictions.or(Restrictions.like("cust_name", "李%"))); criteria.add(Restrictions.like("cust_name", "李%")); List list = criteria.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); }

  4.5、QBC 的统计查询

    @Test
    /**
     * 统计查询,习惯于用 HQL 查询,不习惯用这种
     */
    public void demo5(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Criteria criteria = session.createCriteria(Customer.class);
        /**
         * add                :普通的条件。SQL 语句中where后面条件
         * addOrder            :排序
         * setProjection    :聚合函数 和 group by having
         */
        criteria.setProjection(Projections.rowCount());
        Long num = (Long) criteria.uniqueResult();
        System.out.println(num);
        tx.commit();
    }
    
    @Test
    /**
     * 离线条件查询
     */
    public void demo6(){
        DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);
        detachedCriteria.add(Restrictions.like("cust_name", "李%"));
        
        Session session = HibernateUtils.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        
        Criteria criteria = detachedCriteria.getExecutableCriteria(session);
        List list = criteria.list();
        for (Customer customer : list) {
            System.out.println(customer);
        }
        transaction.commit();
    }

  4.6、离线条件查询(SSH)--DetachedCriteria

  适合综合多添建查询,尤其是带条件,还带分页的查询。用离线条件查询会更方便

 

5、Hibernate 的查询方式:SQL 检索

  SQL查询:通过使用sql语句进行查询

package com.itheima.hibernate.demo1;

import java.util.Arrays;
import java.util.List;

import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * SQL查询
 * @author jt
 *
 */
public class HibernateDemo3 {

    @Test
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
// 把结果封装到对象数组里面面
/*SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer"); List list = sqlQuery.list(); for (Object[] objects : list) { System.out.println(Arrays.toString(objects)); }*/
// 把结果封装到对象里面 SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
// 添加实体 addEntity sqlQuery.addEntity(Customer.
class); List list = sqlQuery.list(); for (Customer customer : list) { System.out.println(customer); } tx.commit(); } }

 

 

 

HQL 的多表查询

  QBC 查询有一些 局限,但有一些多表查询也是可以做的,但是一些特别复杂的就不应行了。

  SQL的多表查询

    1.连接查询

      ① 交叉连接:笛卡尔积(不经常用)

      select * from A,B;

      ② 内连接    :inner join (inner 可以省略)   两个表的交集

        隐式内连接:(看不到关键字,但查到的结果跟显式连接是一样的)

        select * from A,B where A.id = B.aid;

        显式内连接:

        select * from A inner join B on A.id = B.aid;

      ③ 外连接    :一个表的全部,和另外一张表的公共部分

        左外连接:left outer join(outer 可以省略)

        select * from A left outer join B on A.id= B.aid;

        右外连接:right outer join(outer 可以省略)

        select * from A right outer join B on A.id = B.aid;

    2、子查询

  HQL的多表查询

    连接查询

    交叉连接

    内连接

      显示内连接

      隐式内连接

      迫切内连接

    外连接

      左外连接

      右外连接

      迫切左外连接

    @Test
    /**
     * HQL的多表查询
     */
    public void demo9() {
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        // SQL:SELECT * FROM cst_customer c INNER JOIN cst_linkman l ON
        // c.cust_id = l.lkm_cust_id;
        // HQL:内连接 from Customer c inner join c.linkMans
// 普通内连接,把对象封装到一个 Object 类型的数组当中
/* * List list = session.createQuery( * "from Customer c inner join c.linkMans").list(); for (Object[] * objects : list) { System.out.println(Arrays.toString(objects)); } */ // HQL:迫切内连接 其实就在普通的内连接inner join后添加一个关键字fetch. from Customer c inner // join fetch c.linkMans List list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans") .list();// 通知hibernate,将另一个对象的数据封装到该对象中
// 迫切内连接和普通内连接发送的 SQL 语句是一样的
// fetch 关键字的作用是,通知 Hibernate,将另一个对象的数据封装到该对象中
// 普通内连接,封装成了两个对象,一个是客户对象,一个是联系人对象;但是我们客户对象里面已经有联系人对象的集合了,可以把联系人对象的数据拿出来,装到客户对象的集合里面
// 最终得到一个 list,里卖弄放的是 customer 对象,里面就会有联系人的集合;这时候就需要把联系人的集合打印出来,在设置 toString()的时候,把联系人的集合留下来

// 执行程序,会往 customer 里面封装,里面会有联系人的数据。但是会发现一个问题,封装重复了
// 每个 customer 对象里面都有自己关联的联系人的集合,会重复封装
// 可以 select distinct, for (Customer customer : list) { System.out.println(customer); } tx.commit(); }

// 这是迫切内连接,但是迫切内连接一般很少自己手写。我们可以设置一些配置,只要设置了配置,Hibernate 底层就发了一个连接语句去查询,查到以后就给你封装到对象里去。底层其实用的就是迫切内连接
// 现在只要知道迫切内连接的写法,和普通内连接的区别
// 如果需要手动写迫切内连接,记住 distinnct

 

 

 

 

 

Hibernate的抓取策略(优化)

  我们在进行一些相关查询的时候,有时候我们写的,尤其是 HQL 的效率是有些低的。所以就来介绍一下它的抓取策略,是用来对查询关联对象的一种优化。Hibernate 的效率其实并不是特别的高,里面提供了很多种优化的手段。比如说抓取策略、缓存机制,这都是 Hibernate 一些优化的手段。

  实际开发中用不到,用默认值就可以了,但是面试中经常问道。

  抓取策略一般不单独使用,会跟延迟加载一起用,共同进行相应的优化。

1、延迟加载

  延迟加载:lazy(懒加载)。执行到该行代码的时候,不会发送语句去进行查询,在真正使用这个对象的属性的时候才会发送SQL语句进行查询。

延迟加载的分类

  类级别的延迟加载

    指的是通过load方法查询某个对象的时候,是否采用延迟。session.load(Customer.class,1l);

    类级别延迟加载通过(映射)上的lazy进行配置,如果让lazy失效

      ① 将lazy设置为false(只对普通属性有效,对关系对象无效,必须在关联对象上设置 lazy,关联对象才有效)

      ② 将持久化类使用final修饰(不能继承,不能产生代理)

      ③ 调用Hibernate. Initialize()

package com.itheima.hibernate.demo2;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * Hibernate的延迟加载
 * @author jt
 *
 */
public class HibernateDemo1 {

    @Test
    /**
     * 类级别的延迟加载
     * * 在的标签上配置的lazy
     */
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        Customer customer = session.load(Customer.class, 1l);
        Hibernate.initialize(customer);
        System.out.println(customer);
        
        tx.commit();
    }
}

 

  关联级别的延迟加载

    指的是在查询到某个对象的时候,查询其关联的对象的时候,是否采用延迟加载。

      Customer customer = session.get(Customer.class,1l);

      customer.getLinkMans();----通过客户获得联系人的时候,联系人对象是否采用了延迟加载,称为是关联级别的延迟。

    抓取策略往往会和关联级别的延迟加载一起使用,优化语句。

 

2、抓取策略

  2.1、抓取策略的概述

  通过一个对象抓取到关联对象需要发送SQL语句,SQL语句如何发送,发送成什么样格式通过策略进行配置。

    通过或者上通过fetch属性进行设置

      所以就需要知道 fetch 属性和 lazy 属性怎么配对能对 SQL 语句优化达到最优

    fetch和这些标签上的lazy如何设置优化发送的SQL语句

  2.2、上的fetch和lazy

    fetch:抓取策略,控制SQL语句格式

      select                :默认值,发送普通的select语句,查询关联对象

      join                    :发送一条迫切左外连接查询关联对象

      subselect         :发送一条子查询查询其关联对象

    lazy:延迟加载,控制查询关联对象的时候是否采用延迟(上的值只要true和false)

      true                   :默认值,查询关联对象的时候,采用延迟加载

      false                  :查询关联对象的时候,不采用延迟加载

      extra                 :及其懒惰。

    在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join(可以减少与服务器交互次数)

package com.itheima.hibernate.demo2;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.domain.LinkMan;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * 在上的fetch和lazy
 * @author jt
 *
 */
public class HibernateDemo2 {

    @Test
    /**
     * 默认情况:
     */
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 查询1号客户
        Customer customer = session.get(Customer.class, 1l);// 发送一条查询客户的SQL
        System.out.println(customer.getCust_name());
        // 查看1号客户的每个联系人的信息
        for (LinkMan linkMan : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL
            System.out.println(linkMan.getLkm_name());
        }
        tx.commit();
    }
    
    @Test
    /**
     * 设置fetch="select" lazy="true"
     */
    public void demo2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 查询1号客户
        Customer customer = session.get(Customer.class, 1l);// 发送一条查询客户的SQL
        System.out.println(customer.getCust_name());
        // 查看1号客户的每个联系人的信息
        for (LinkMan linkMan : customer.getLinkMans()) {// 发送一条根据客户ID查询联系人的SQL
            System.out.println(linkMan.getLkm_name());
        }
        tx.commit();
    }
    
    @Test
    /**
     * 设置    fetch="select" lazy="false"
     */
    public void demo3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 查询1号客户
        Customer customer = session.get(Customer.class, 1l);// 发送两条SQL语句:查询客户的名称,查询客户关联联系人
        System.out.println(customer.getCust_name());
        /*// 查看1号客户的每个联系人的信息
        for (LinkMan linkMan : customer.getLinkMans()) {// 
            System.out.println(linkMan.getLkm_name());
        }*/
        
        System.out.println(customer.getLinkMans().size());
        tx.commit();
    }
    
    @Test
    /**
     * 设置fetch="select" lazy="extra"
     */
    public void demo4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 查询1号客户
        Customer customer = session.get(Customer.class, 1l);// 发送一条查询1号客户的SQL语句
        System.out.println(customer.getCust_name());
        
        System.out.println(customer.getLinkMans().size());// 发送一条select count() from ...;通过聚合函数提供效率
        tx.commit();
    }
    
    @Test
    /**
     * 设置fetch="join" lazy=失效
     */
    public void demo5(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        // 查询1号客户
        Customer customer = session.get(Customer.class, 1l);// 发送一条迫切左外连接查询记录
        System.out.println(customer.getCust_name());
        
        System.out.println(customer.getLinkMans().size());// 不发送
        tx.commit();
    }
    
    @SuppressWarnings("unchecked")
    @Test
    /**
     * 设置fetch="subselect" lazy="true"
     */
    public void demo6(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        List list = session.createQuery("from Customer").list();// 发送查询所有客户的SQL
        for (Customer customer : list) {
            System.out.println(customer.getCust_name());
// 不能查询一条记录去测试
// in 后面只有一个值,效率没有 = 高,Hibernate 只能替换为 = ,就没有子查询了 System.out.println(customer.getLinkMans().size());
// 发送一条子查询 } tx.commit(); } @SuppressWarnings("unchecked") @Test /** * 设置fetch="subselect" lazy="false" */ public void demo7(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List list = session.createQuery("from Customer").list();// 发送查询所有客户的SQL,发送一条子查询 for (Customer customer : list) { System.out.println(customer.getCust_name()); System.out.println(customer.getLinkMans().size());// } tx.commit(); } }

  fetch控制SQL语句格式,lazy 控制语句发送实机

  2.3、上的fetch和lazy

  fetch :抓取策略,控制SQL语句格式。

    select       :默认值,发送普通的select语句,查询关联对象。

    join           :发送一条迫切左外连接。

  lazy   :延迟加载,控制查询关联对象的时候是否采用延迟。

    proxy        :默认值,proxy具体的取值,取决于另一端的上的lazy的值。

    false         :查询关联对象,不采用延迟。

    no-proxy  :(不会使用)

  在实际开发中,一般都采用默认值。如果有特殊的需求,可能需要配置join

package com.itheima.hibernate.demo2;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.LinkMan;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * many-to-one上的fetch和lazy测试
 * @author jt
 *
 */
public class HibernateDemo3 {

    @Test
    /**
     * 默认值
     */
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句
        System.out.println(linkMan.getLkm_name());
        System.out.println(linkMan.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户
        
        tx.commit();
    }
    
    @Test
    /**
     * fetch="select" lazy="proxy"
     */
    public void demo2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句
        System.out.println(linkMan.getLkm_name());
        System.out.println(linkMan.getCustomer().getCust_name());// 发送一条select语句查询联系人所关联的客户
        
        tx.commit();
    }
    
    @Test
    /**
     * fetch="select" lazy="false"
     */
    public void demo3(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条查询联系人语句,发送一条select语句查询联系人所关联的客户
        System.out.println(linkMan.getLkm_name());
        System.out.println(linkMan.getCustomer().getCust_name());// 
        
        tx.commit();
    }
    
    @Test
    /**
     * fetch="join" lazy=失效
     */
    public void demo4(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        LinkMan linkMan = session.get(LinkMan.class, 1l);// 发送一条迫切左外连接查询联系人所关联的客户。
        System.out.println(linkMan.getLkm_name());
        System.out.println(linkMan.getCustomer().getCust_name());// 
        
        tx.commit();
    }
}

 

批量抓取

  一批关联对象一起抓取,batch-size

package com.itheima.hibernate.demo2;

import java.util.List;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test;

import com.itheima.hibernate.domain.Customer;
import com.itheima.hibernate.domain.LinkMan;
import com.itheima.hibernate.utils.HibernateUtils;

/**
 * 批量抓取
 * @author jt
 *
 */
public class HibernateDemo4 {

    @SuppressWarnings("unchecked")
    @Test
    /**
     * 获取客户的时候,批量抓取联系人
     * 在Customer.hbm.xml中set上配置batch-size
     */
    public void demo1(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        List list = session.createQuery("from Customer").list();
        for (Customer customer : list) {
            System.out.println(customer.getCust_name());
            for (LinkMan linkMan : customer.getLinkMans()) {
                System.out.println(linkMan.getLkm_name());
            }
        }
        tx.commit();
    }
    
    @SuppressWarnings("unchecked")
    @Test
    /**
     * 获取联系人的时候,批量抓取客户
     * * 在Customer.hbm.xml中上配置
     */
    public void demo2(){
        Session session = HibernateUtils.getCurrentSession();
        Transaction tx = session.beginTransaction();
        
        List list = session.createQuery("from LinkMan").list();
        for (LinkMan linkMan : list) {
            System.out.println(linkMan.getLkm_name());
            System.out.println(linkMan.getCustomer().getCust_name());
        }
        tx.commit();
    }
}

转载于:https://www.cnblogs.com/xifengbuqi/p/9738649.html

你可能感兴趣的:(Hibernate(四) - HQL_QBC查询详解--抓取策略优化机制)