1. Hibernate的查询方式

  • 在Hibernate中提供了5种查询方式。

1.1 方式一:OID查询

  • OID查询:Hibernate根据对象的OID(主键)进行检索。
  • 使用get()方法
    • Customer customer = session.get(Customer.class,1L);
  • 使用load()方法
    • Customer customer = session.load(Custoemr.class,1L);

1.2 方式二:对象导航查询

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

    LinkMan linkMan = session.get(LinkMan.class,1L);
    Customer customer = linkMan.getCustomer(); Customer customer = session.get(Customer.class,2L);
    Set<LinkMan> linkMans = customer.getLinkMans();

1.3 方式三:HQL方式

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

1.4 方式四:QBC查询

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

1.5 方式五:SQL查询

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

2. 环境搭建

  • 创建一个新项目,导入相关jar包

  • 新建数据库,新建数据表,分别为cst_custoemr和cst_linkman

  • 新建两个实体,分别为Customer和LinkMan

    • Customer中生成toString方法,不包含LinkMan
    • LinkMan中生成toString方法,不包含Customer
  • 准备工具类,配置文件,映射文件

  • 生成测试的数据,该方法执行3次

    /**
    * HQL的查询方式的测试类
    * @author itzhouq
    *
    */
    public class HibernateDemo1 { @Test
    public void test1() {
    Session session = HibernateUtils.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Customer customer = new Customer();
    customer.setCust_name("莫尔德");
    for (int i = 0; i < 10; i++) {
    LinkMan linkMan = new LinkMan();
    linkMan.setLkm_name("老马"+i); customer.getLinkMans().add(linkMan); session.save(linkMan);
    }
    session.save(customer);
    transaction.commit(); }
    }

3. HQL查询

3.1 简单查询

@Test
public void test2() {//HQL的简单查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 简单查询
Query query = session.createQuery("from Customer");
List<Customer> list = query.list(); // sql中支持*号的写法:select * from cst_customer;但是在HQL中不支持*号的写法。
// Query query2 = session.createQuery("select * from from Customer");// 报错
// List<Customer> list2 = query.list(); for (Customer customer : list) {
System.out.println(customer); }
transaction.commit();
}

3.2 别名查询

@Test
public void test3() {// 别名查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = 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); }
transaction.commit();
}

3.3 排序查询

@Test
public void test5() {// 排序查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = 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); }
transaction.commit();
}

3.4 条件查询

@Test
public void test4() {// 排序查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 排序查询
// 1. 按位置绑定:根据参数的位置进行绑定
// 一个条件
// Query query = session.createQuery("from Customer where cust_name = ?");
// query.setParameter(0, "朱元璋"); // 多个条件
// Query query = session.createQuery("from Customer where cust_source = ? and cust_name like ?");
// query.setParameter(0, "朋友推荐");
// query.setParameter(1, "朱%"); // 2. 按名称绑定
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); }
transaction.commit();
}

3.4 投影查询

  • 投影查询:查询对象的某个或某些属性
@Test
public void test6() {// 投影查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 投影查询
// 单个属性
// List<Object> list = session.createQuery("select c.cust_name from Customer c").list();
// for (Object customer : list) {
// System.out.println(customer);
//
// } // 多个属性:
// 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<Object[]> list = session.createQuery("select c.cust_name,c.cust_source from Customer c").list();
for (Object[] customer : list) {
System.out.println(Arrays.toString(customer));
} transaction.commit();
}

3.5 分页查询

@Test
public void test7() {// 分页查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 分页查询
Query query = session.createQuery("from LinkMan");
query.setFirstResult(20);
query.setMaxResults(5);
List<LinkMan> list = query.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
} transaction.commit();
}

3.6 分组统计查询

@Test
public void test8() {// 分组统计查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
// 分组统计查询
Object object = session.createQuery("select count(*) from Customer").uniqueResult();
System.out.println(object); //分组统计:
Query query = session.createQuery("select cust_source,count(*) from Customer group by cust_source");
List<Object[]> list = query.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
transaction.commit();
}

3.7 HQL的多表查询

3.7.1 SQL的多表查询

  • 连接查询

    • 交叉连接:笛卡尔积
    • 内连接:innner join(inner可以省略)
      • 隐式内连接:select * from A,B where A.id = B.aid;
      • 显式内连接:select * from A inner join B on A.id = B.aid;
    • 外连接:outer可以省略
      • 左外连接:select * from A left outer join B on A.id = B.id;
      • 右外连接:select * from A right outerjoin B on A.id = B.id;
  • 子查询

3.7.2 HQL的多表查询

  • 连接查询

    • 交叉连接
    • 内连接:
      • 显式内连接
      • 隐式内连接
      • 迫切内连接
    • 外连接:
      • 左外连接
      • 右外连接
      • 迫切左外连接
@Test
public void test7() { // 多表查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = 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.
// 迫切内连接的到的是一个对象,在Customer的toString中给定LinkMans可以得到全部字段
List<Customer> list2 = session.createQuery("select distinct c from Customer c inner join fetch c.linkMans").list();
for (Customer customer : list2) {
System.out.println(customer);
} transaction.commit();
}

4. QBC查询

4.1 简单查询

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

4.2 排序查询

@Test
public void test2() { // 排序查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//获得Criteria的对象
Criteria criteria = session.createCriteria(Customer.class);
// criteria.addOrder(Order.desc("cust_id")); // 降序
criteria.addOrder(Order.asc("cust_id")); // 升序
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
} transaction.commit();
}

4.3 分页查询

@Test
public void test3() { // 分页查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//获得Criteria的对象
Criteria criteria = session.createCriteria(LinkMan.class);
criteria.setFirstResult(20);
criteria.setMaxResults(5); List<LinkMan> list = criteria.list();
for (LinkMan linkMan : list) {
System.out.println(linkMan);
} transaction.commit();
}

4.4 条件查询

@Test
public void test4() { // 条件查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//获得Criteria的对象
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.like("cust_name", "李%"));
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
} transaction.commit();
}

4.5 统计查询

@Test
public void test5() { // 条件查询
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction();
//获得Criteria的对象
Criteria criteria = session.createCriteria(Customer.class);
/**
* add :普通的条件。where后面条件
* addOrder:排序
* setProjecttion:聚合函数和group by having
*/ criteria.setProjection(Projections.rowCount());
Long num = (Long) criteria.uniqueResult();
System.out.println(num); transaction.commit();
}

4.6 离线条件查询(***)DetachedCriteria

  • 离线条件查询在前台需要传递多个条件,用于筛选的时候很方便,可以不用在dao层拼接字符串

  • 代码

@Test
public void test6() { // 离线条件查询
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();
}

5. SQL查询


@Test
public void test1() {
Session session = HibernateUtils.getCurrentSession();
Transaction transaction = session.beginTransaction(); // 调用的createSQLQuery,返回的值遍历后是数组形式的集合
// 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); //封装到实体Customer中
List<Customer> list = sqlQuery.list();
for (Customer customer : list) {
System.out.println(customer);
} transaction.commit();
}

6. Hibernate的抓取策略

6.1 延迟加载的概述

6.1.1 什么是延迟加载

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

6.1.2 延迟加载的分类

  • 类级别的延迟加载

    • 指的是通过load方法查询某个对象的时候,是否采用延迟加载。session.load(Customer.class,1L);
    • 类级别的延迟加载通过<class>上的lazy进行配置。让lazy失效的方法有:
      • 将lazy设置为false
      • 将持久化类使用final修改
      • Hibernate.ininialize()
  • 关联级别的延迟加载

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

      Customer customer = session.get(Customer.class,1L);
      customer.getLinkMans();
      //通过客户获得联系人的时候,联系人对象是否采用了延迟记载,称为关联级别的延迟加载。
    • 抓取策略往往会和关联级别的延迟加载一起使用,优化语句。

6.2 抓取策略

Customer.hbm.xml

<set name="linkMans" fetch="select" lazy="true">
<!-- column多的一方的外键的名称 -->
<key column="lkm_cust_id"></key>
<!-- class:多的一方的类的全限定名 -->
<one-to-many class="com.itzhouq.hibernate.domain.LinkMan"/>
</set>

6.2.1 抓取策略概述

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

    • 通过<set>或者<many-to-one>上的fetch属性进行配置
    • fetch和这些标签上的lazy如何设置,优化发送的SQL语句。

6.2.2 set上的fetch和lazy

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

    • select:默认值,发送普通的select语句,查询关联对象
    • join:发送一条迫切左外连接查询关联对象。
    • subeselect:发送一条子查询查询其关联对象。
  • lazy:延迟加载,控制查询关联对象的时候是否采用延迟加载
    • true:默认值,查询关联对象的时候,采用延迟加载
    • false:查询关联对象的时候,不采用延迟加载
    • extra:及其懒惰。
  • 实际开发过程中,一般采用默认值。如果有特殊需求,可能需要配置join。

6.2.3 many-to-one上的fetch和lazy

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

    • select:默认值,发送普通的select语句,查询关联对象。
    • join:发送一条迫切左外连接
  • lazy:延迟加载,控制查询关联对象的时候是否采用延迟加载
    • proxy:默认值,proxy具体的取值,取决于另一端的class上的lazy的值。
    • false:查询关联对象,不采用延迟。
    • no-proxy:不用
  • 在实际开发过程中,一般采用默认值。如果有特殊的需求,可能需要配置join。

6.2.4 批量抓取

  • 一批关联对象一起抓取,betch-size。

    package com.itzhouq.hibernate.demo;
    
    import java.util.List;
    
    import org.hibernate.Session;
    import org.hibernate.Transaction;
    import org.junit.Test; import com.itzhouq.hibernate.domain.Customer;
    import com.itzhouq.hibernate.domain.LinkMan;
    import com.itzhouq.hibernate.utils.HibernateUtils; /*
    * 批量抓取测试
    */
    public class HibernateDemo4 { @Test
    public void test1() {
    // 获取客户的时候,批量抓取联系人
    // 在Customer.hbm.xml中set上配置batch-size
    Session session = HibernateUtils.getCurrentSession();
    Transaction transaction = 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());
    }
    } transaction.commit();
    }
    }
    <set name="linkMans" batch-size="5">
    <!-- column多的一方的外键的名称 -->
    <key column="lkm_cust_id"></key>
    <!-- class:多的一方的类的全限定名 -->
    <one-to-many class="com.itzhouq.hibernate.domain.LinkMan"/>
    </set>

Hibernate框架笔记04HQL_QBC查询详解_抓取策略优化机制的更多相关文章

  1. Hibernate学习第4天--HQL——QBC查询详解,抓取策略优化。

    上次课回顾: l  Hibernate的一对多 n  表与表之间关系 u  一对多关系 u  多对多关系 u  一对一关系 n  Hibernate的一对多配置 u  搭建Hibernate基本环境 ...

  2. 分享知识-快乐自己:Hibernate 中Criteria Query查询详解

    1):Hibernate 中Criteria Query查询详解 当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中. 此外,Hibernate还支持Cr ...

  3. 详解usbmon抓取的log各字段的含义

    详解 usbmon 抓取的 log 各字段的含义 在上篇文章中,我们已经介绍了如何在 linux 下使用 usbmon 抓取 usb 总线上数据的方法.(https://www.cnblogs.com ...

  4. Hibernate框架学习(二)——api详解

    一.Configuration对象 功能:配置加载类,用于加载主配置,orm元数据加载. //1.创建,调用空参构造(还没有读配置文件) Configuration conf=new Configur ...

  5. Hibernate学习笔记--映射配置文件详解

    参考资料: http://blog.163.com/hzd_love/blog/static/13199988120108265317988/ http://www.cnblogs.com/often ...

  6. Hibernate 中Criteria Query查询详解【转】

    当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中.此外,Hibernate还支持Criteria查询(Criteria Query),这种查询方式把查询 ...

  7. 深度学习Keras框架笔记之激活函数详解

    激活函数也是神经网络中一个很重的部分.每一层的网络输出都要经过激活函数.比较常用的有linear,sigmoid,tanh,softmax等.Keras内置提供了很全的激活函数,包括像LeakyReL ...

  8. 【转】Hibernate 原汁原味的四种抓取策略

    最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog ...

  9. Hibernate 原汁原味的四种抓取策略(转)

    原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html     尊重原作者,访问原创地址 最近在研究 Hibernate ...

随机推荐

  1. leetcode python快乐数

    编写一个算法来判断一个数是不是“快乐数” “快乐数”的定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复该过程直到为1,也可能是无限循环但始终变不到1. 如果可以变为1,那 ...

  2. Apt下载安装包时Hash校验和不符

    近期我的电脑在使用apt-get或aptitude下载Linux安装包时总是出现如下图所示的Hash校验和不符的问题.以至于下载过程被频繁中断,不得不反复运行apt-get或者在aptitude中按g ...

  3. js中的严格模式和非严格模式的比较

    前言 es5的严格模式是采用具有限制性JavaScript变体的一种方式,从而使代码显示地脱离'懒散模式/非严格模式' 严格模式 严格模式通过抛出错误来消除一些原有静默错误 严格模式修复了一些导致Ja ...

  4. android新窗口以及传值

    1,新建一个activity,如Activity2,在清单文件AndroidManifest.xml 中 application节点中 增加一个新窗体: ................. </ ...

  5. angular2报错

    1.运行ng serve的时候卡在95% emitting LicenseWebpackPlugin 放弃使用cnpm,使用yarn 删除node_modules (不需要删除project目录重新n ...

  6. 【Vue】动态加载Html片段

    在编写Vue页面的时候,会碰到这么一个需求.由于页面组件比较多,不可能一次性将所有的页面都打包,只能按需获取相应的页面进行显示. 比如有一个App页面,需要异步获取html片段通过v-html指令加载 ...

  7. Ubuntu 下使用 Nginx 部署 .NET Core 2.0 网站

    前言 本文介绍如何在 Ubuntu 16.04 服务器上安装 .NET Core 2.0 SDK.创建项目与发布,并使用 Nginx 部署 .NET Core 2.0 Web 项目. 安装 .NET ...

  8. MyBatis sqlsession 简化 使用工具类创建

    2019-04-09 @Test public void Test() throws Exception { // 1.读取配置文件 String resource = "mybatis-c ...

  9. Python 中关于Random的使用方法

    Random 在 Python 中的使用方法: 1.random.random(): 会随机生成0-1之间的小数 例如: 2.random.uniform(min,max): 会随机生成 min - ...

  10. 【C语言编程练习】5.11 猴子吃桃子问题

    1. 问题描述 有一只猴子,第一天摘下若干个桃子,当即吃掉了一半,又多吃了一个,第二天又将剩下的桃子吃掉了一半,又多吃了一个,按照这样的吃法,每天都吃前一天吃下的桃子的一半又一个.到第十天,就剩下了一 ...