4、Hibernate的查询方式

  • 2019 年 11 月 10 日
  • 筆記

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

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

1-1、使用get方法

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

1-2、使用load方法

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

 

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

Customer customer = session.get(Customer.class,1L);  Set<LinkMan> linkManSet = customer.getLinkMans();

 

4-1、HQL查询

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

package com.turtle.test;    import java.util.Arrays;  import java.util.List;    import com.turtle.dao.Customer;  import com.turtle.dao.LinkMan;  import com.turtle.utils.HibernateUtils;  import org.hibernate.Query;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;      /**   * HQL的查询方式的测试类   *   * @author jt   *   */  public class Hibernater_01 {        @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();      }        @Test      /**       * HQL的简单查询       */      public void demo2() {          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();          // 简单的查询          Query query = session.createQuery("from Customer");          List<Customer> list = query.list();            // sql中支持*号的写法:select * from cst_customer; 但是在HQL中不支持*号的写法。          /*           * Query query = session.createQuery("select * from Customer");// 报错           * List<Customer> list = query.list();           */            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @Test      /**       * 别名查询       */      public void demo3() {          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();          // 别名的查询          /*           * Query query = session.createQuery("from Customer c"); List<Customer>           * list = query.list();           */            Query query = session.createQuery("select c from Customer c");          List<Customer> list = query.list();            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @Test      /**       * 排序查询       */      public void demo4() {          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();          // 排序的查询          // 默认情况          // List<Customer> list = session.createQuery("from Customer order by          // cust_id").list();          // 设置降序排序 升序使用asc 降序使用desc          List<Customer> list = session.createQuery("from Customer order by cust_id desc").list();            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @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<Customer> list = query.list();           */            // 多个条件          /*           * Query query = session.createQuery(           * "from Customer where cust_source = ? and cust_name like ?");           * query.setParameter(0, "小广告");           * query.setParameter(1, "李%");           * List<Customer> 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<Customer> list = query.list();            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @Test      /**       * 投影查询       */      public void demo6() {          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            // 投影查询          // 单个属性          /*           * List<Object> list = session.createQuery("select c.cust_name from Customer c").list();           * for (Object object :list) {           *      System.out.println(object);            * }           */            // 多个属性:          /*           * List<Object[]> 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<Customer> list = session.createQuery("select new Customer(cust_name,cust_source) from Customer").list();          for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @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<LinkMan> list = query.list();            for (LinkMan linkMan : list) {              System.out.println(linkMan);          }          tx.commit();      }        @Test      /**       * 分组统计查询       */      public void demo8() {          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            // 聚合函数的使用:count(),max(),min(),avg(),sum()          Object object = session.createQuery("select count(*) from Customer").uniqueResult();          System.out.println(object);          // 分组统计:          List<Object[]> 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();      }        @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          /*           * List<Object[]> 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<Customer> list = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans")                  .list();// 通知hibernate,将另一个对象的数据封装到该对象中            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }    }

 

 

4-2、 HQL的多表查询

  SQL的多表查询

  连接查询

  交叉连接:笛卡尔积

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;

  子查询

 

 HQL的多表查询

  连接查询

  交叉连接

  内连接

  显示内连接

  隐式内连接

  迫切内连接

  外连接

  左外连接

  右外连接

  迫切左外连接

 

5、QBC查询:Query By Criteria,条件查询。是一种更加面向对象化的查询的方式。

package com.turtle.test;    import java.util.List;    import com.turtle.dao.Customer;  import com.turtle.dao.LinkMan;  import com.turtle.utils.HibernateUtils;  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;      /**   * QBC的查询   * @author jt   *   */  public class Hibernater_02 {        @Test      /**       * 简单的查询       */      public void demo1(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            // 获得Criteria的对象          Criteria criteria = session.createCriteria(Customer.class);          List<Customer> list = criteria.list();            for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @Test      /**       * 排序查询       */      public void demo2(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            // 排序查询          Criteria criteria = session.createCriteria(Customer.class);  //        criteria.addOrder(Order.asc("cust_id")); // 升序          criteria.addOrder(Order.desc("cust_id")); // 降序          List<Customer> list = criteria.list();            for (Customer customer : list) {              System.out.println(customer);          }            tx.commit();      }        @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<LinkMan> list = criteria.list();            for (LinkMan linkMan : list) {              System.out.println(linkMan);          }          tx.commit();      }        @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           */          criteria.add(Restrictions.eq("cust_source", "小广告"));  //        criteria.add(Restrictions.or(Restrictions.like("cust_name", "李%")));          criteria.add(Restrictions.like("cust_name", "李%"));          List<Customer> list = criteria.list();          for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }        @Test      /**       * 统计查询       */      public void demo5(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            Criteria criteria = session.createCriteria(Customer.class);          /**           * add                :普通的条件。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<Customer> list = criteria.list();          for (Customer customer : list) {              System.out.println(customer);          }          transaction.commit();      }  }

 

                                                                   

 

 

 

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

package com.turtle.test;    import java.util.Arrays;  import java.util.List;    import com.turtle.dao.Customer;  import com.turtle.utils.HibernateUtils;  import org.hibernate.SQLQuery;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;    /**   * SQL查询   * @author jt   *   */  public class Hibernate_03 {        @Test      public void demo1(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            /*SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");          List<Object[]> list = sqlQuery.list();          for (Object[] objects : list) {              System.out.println(Arrays.toString(objects));          }*/            SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");          // 这样就可以操作对应的对象了          sqlQuery.addEntity(Customer.class);          List<Customer> list = sqlQuery.list();          for (Customer customer : list) {              System.out.println(customer);          }          tx.commit();      }  }

 

 

二、 Hibernate的抓取策略(优化)

1、   延迟加载

什么是延迟加载

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

延迟加载的分类

  类级别的延迟加载

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

  类级别延迟加载通过<class>上的lazy进行配置,如果让lazy失效

  将lazy设置为false

  将持久化类使用final修饰

  Hibernate. Initialize()

  关联级别的延迟加载

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

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

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

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

package com.turtle.test2;    import com.turtle.dao.Customer;  import com.turtle.utils.HibernateUtils;  import org.hibernate.Hibernate;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;      /**   * Hibernate的延迟加载   * @author jt   *   */  public class Hibernate_01 {        @Test      /**       * 类级别的延迟加载       * * 在<class>的标签上配置的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();      }  }

 

2、抓取策略

 抓取策略的概述

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

  通过<set>或者<many-to-one>上通过fetch属性进行设置

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

2-1  <set>上的fetch和lazy

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

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

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

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

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

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

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

    extra                     :及其懒惰。

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

package com.turtle.test2;    import java.util.List;    import com.turtle.dao.Customer;  import com.turtle.dao.LinkMan;  import com.turtle.utils.HibernateUtils;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;      /**   * 在<set>上的fetch和lazy   * @author jt   *   */  public class Hibernate_02 {        @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<Customer> 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();      }        @SuppressWarnings("unchecked")      @Test      /**       * 设置fetch="subselect" lazy="false"       */      public void demo7(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            List<Customer> 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();      }  }

 

 2-1<many-to-one>上的fetch和lazy

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

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

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

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

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

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

   no-proxy :(不会使用)

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

package com.turtle.test2;    import com.turtle.dao.LinkMan;  import com.turtle.utils.HibernateUtils;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;      /**   * many-to-one上的fetch和lazy测试   * @author jt   *   */  public class Hibernate_03 {        @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();      }  }

 

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

package com.turtle.test2;    import java.util.List;    import com.turtle.dao.Customer;  import com.turtle.dao.LinkMan;  import com.turtle.utils.HibernateUtils;  import org.hibernate.Session;  import org.hibernate.Transaction;  import org.junit.Test;      /**   * 批量抓取   * @author jt   *   */  public class Hibernate_04 {        @SuppressWarnings("unchecked")      @Test      /**       * 获取客户的时候,批量抓取联系人       * 在Customer.hbm.xml中set上配置batch-size       */      public void demo1(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            List<Customer> 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中<class>上配置       */      public void demo2(){          Session session = HibernateUtils.getCurrentSession();          Transaction tx = session.beginTransaction();            List<LinkMan> 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();      }  }