Hibernate框架笔记04HQL_QBC查询详解_抓取策略优化机制

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
- 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()
- 指的是通过load方法查询某个对象的时候,是否采用延迟加载。
关联级别的延迟加载
指的是在查询到某个对象的时候,查询其关联对象的时候,是否采用延迟加载。
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查询详解_抓取策略优化机制的更多相关文章
- Hibernate学习第4天--HQL——QBC查询详解,抓取策略优化。
上次课回顾: l Hibernate的一对多 n 表与表之间关系 u 一对多关系 u 多对多关系 u 一对一关系 n Hibernate的一对多配置 u 搭建Hibernate基本环境 ...
- 分享知识-快乐自己:Hibernate 中Criteria Query查询详解
1):Hibernate 中Criteria Query查询详解 当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中. 此外,Hibernate还支持Cr ...
- 详解usbmon抓取的log各字段的含义
详解 usbmon 抓取的 log 各字段的含义 在上篇文章中,我们已经介绍了如何在 linux 下使用 usbmon 抓取 usb 总线上数据的方法.(https://www.cnblogs.com ...
- Hibernate框架学习(二)——api详解
一.Configuration对象 功能:配置加载类,用于加载主配置,orm元数据加载. //1.创建,调用空参构造(还没有读配置文件) Configuration conf=new Configur ...
- Hibernate学习笔记--映射配置文件详解
参考资料: http://blog.163.com/hzd_love/blog/static/13199988120108265317988/ http://www.cnblogs.com/often ...
- Hibernate 中Criteria Query查询详解【转】
当查询数据时,人们往往需要设置查询条件.在SQL或HQL语句中,查询条件常常放在where子句中.此外,Hibernate还支持Criteria查询(Criteria Query),这种查询方式把查询 ...
- 深度学习Keras框架笔记之激活函数详解
激活函数也是神经网络中一个很重的部分.每一层的网络输出都要经过激活函数.比较常用的有linear,sigmoid,tanh,softmax等.Keras内置提供了很全的激活函数,包括像LeakyReL ...
- 【转】Hibernate 原汁原味的四种抓取策略
最近在研究 Hibernate 的性能优化的时候碰到了"抓取策略", 由于以前没有详细的研究过, 所以到处找资料, 但是无论从一些讲 Hibernate 书籍,还是他人 Blog ...
- Hibernate 原汁原味的四种抓取策略(转)
原文出处:http://www.cnblogs.com/rongxh7/archive/2010/05/12/1733088.html 尊重原作者,访问原创地址 最近在研究 Hibernate ...
随机推荐
- 使用 Fetch
原文链接:https://css-tricks.com/using-fetch/. 本文介绍了Fetch基本使用方法及zlFetch库的使用 无论用JavaScript发送或获取信息,我们都会用到Aj ...
- vue 事件修饰符
1.用.stop来阻止冒泡(点击click按钮之后,先执行clickBtn2方法,然后执行clickBtn1方法,.stop命令阻止了clickBtn1方法的执行) 2.使用.prevent命令来阻止 ...
- django framework相关的错误信息
错误信息1: 报错信息: TypeError: In order to allow non-dict objects to be serialized set the safe parameter t ...
- 使用JumpServer管理你的服务器
本文介绍CentOS 7从安装jumpserver到简单使用jumpserver管理服务器. 1.Jumpserver介绍 Jumpserver是一款开源的开源的堡垒机,如下图是官网介绍. 官网地址: ...
- StackExchange.Redis超时的问题
最近公司有个项目,在请求量大的情况下,有大量的错误日志是关于redis超时的问题: Timeout performing SET XXX, inst: 27, mgr: ProcessReadQueu ...
- C++第二课:指针常用法[个人见解]
在小编这里,没有任何学习知识的顺序,写到的东西对初学者肯定是有用处的,前提,你真的把C语言学完的那些初学者. 在讲明指针的知识前,或许有人一直说不会指针你学不会C++,或者说你所学C++的深度,全凭你 ...
- user-agent | what is the "user-agent" ?
User Agent(用户代理) UA是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等 通过抓包可以得到 下面是几个 ...
- BZOJ1431 : MLand
考虑任意一棵生成树,它的代价是一个一次函数. 因此所有生成树的最小值随着时间变化呈现出的是一个上凸壳. 三分查找最大值即可. 时间复杂度$O(m\log m\log w)$. #include< ...
- ZOJ4043 : Virtual Singers
将所有$A$和$B$混在一起排序,那么每个$B$要匹配一个$A$,从左往右依次考虑每个数: 如果是一个$B$: 如果左边没有多余的$A$,那么将其放入堆$q_C$中,表示这个$B$还未匹配. 否则选择 ...
- NOIP-Vigenère密码
题目描述 16 世纪法国外交家 Blaise de Vigenère 设计了一种多表密码加密算法―― Vigenère 密码. Vigenère 密码的加密解密算法简单易用,且破译难度比较高,曾在美国 ...