Hibernate查询、 检索、 抓取 (Fetch)

本小妞迷上赌 提交于 2019-12-01 19:59:50
一、HQL
在hql中关键字不区分大小写,但属性和类名区分大小写

1. 简单属性查询
  * 单一属性查询,返回结果集属性列表
  * 多个属性查询,返回集合元素是对象数组,数组长度取决于select中属性个数
  * 返回数组不够对象化,可以采用hql动态实例化对象
    e.g:  select new Student(name, age) from Student;

2. 实体对象查询
  * N + 1问题,在默认情况下,使用query.iterate查询, 可能出现N + 1问题
    发出N+1条sql语句
    1: 首先发出一条查询id列表的SQL
    N: 根据id列表到缓存中查询,如果缓存未命中,则根据ID发出N条相应sql
  * list和iterated 区别
    > list :  每次都会发出SQL语句,list会向缓存中放入数据,而不利用缓存的数据
    > iterate :  在默认情况下iterate利用缓存数据,但在缓存中根据ID未命中则可能出现N+1问题

3. 条件查询
  * 可以采用拼接字符串的方式传递参数
  * 可以采用 ?来传递参数(索引从0开始)
  * 可以采用 :参数名 来传递

4. 本地SQL查询
5. 外置命名查询
6. 分页查询
7. 对象导航查询
9. 连接查询 (内连,外连)
  * 内连接
     select c.name, s.name from Student s  join s.classes c
  * 外连接(左连接/右连接)
     left:   select c.name, s.name from Classes c left join c.students s
     right: select c.name, s.name from Classes c right join c.students s

10. 统计查询
11. DML风格的操作(尽量少用,因为和缓存不同步)


二、 检索

Order --> Customer
1.  立即检索策略  lazy="false"

select c from Customer c
如果查询n个Customer对象,那么必须执行N+1次select查询,这种策略没有利用SQL的连接查询

可以执行一条左外连接查询所有数据
select * from CUSTOMER left outer join ORDERS on ....

2.  延迟检索策略
对于<set>元素优先考虑延迟检索, 设置lazy="true"
Customer对象的orders变量引用集合代理类实例, 当第一次访问它时,Hibernate会初始化这个集合代理类实例, 在初始化过程中到数据库中检索所有与Customer关联的Order对象,执行select语句:

select * from ORDERS where CUSTOMER_ID=1;

缺点: 
应用程序如果希望访问游离状态的代理类实例,必须保证它在持久化状态时已经被初始化

lazy策略可以用在:

* <class>标签上:可以取值true/false
* <property>标签上,可以取值true/false,这个特性需要类增强
* <set>/<list>等集合上,可以取值为true/false/extra
* <one-to-one>/<many-to-one>等标签上,可以取值false/proxy/no-proxy

>>  getload的区别:

* get不支持延迟加载,而load支持。
* 当查询特定的数据库中不存在的数据时,get会返回null,而load则抛出异常。

>>  类(Class)的延迟加载

* 设置<class>标签中的lazy="true",或是保持默认(即不配置lazy属性)
* 如果lazy的属性值为true,那么在使用load方法加载数据时,只有确实用到数据的时候才会发出sql语句;这样有可能减少系统的开销。

>> 集合(collection)的延迟加载:可以取值truefalseextra

* true:默认取值,它的意思是只有在调用这个集合获取里面的元素对象时,才发出查询语句,加载其集合元素的数据
* false:取消懒加载特性,即在加载对象的同时,就发出第二条查询语句加载其关联集合的数据
* extra: 推荐使用, 一种比较聪明的懒加载策略,即调用集合的size/contains等方法的时候,hibernate并不会去加载整个集合的数据,而是发出一条聪明的SQL语句,以便获得需要的值,只有在真正需要用到这些集合元素对象数据的时候,才去发出查询语句加载所有对象的数据

>> Hibernate单端关联懒加载策略:即在<one-to-one>/<many-to-one>标签上可以配置懒加载策略。可以取值为:false/proxy/no-proxy

* false: 取消懒加载策略,即在加载对象的同时,发出查询语句,加载其关联对象
* proxy: 这是hibernate对单端关联的默认懒加载策略,即只有在调用到其关联对象的方法的时候才真正发出查询语句查询其对象数据,其关联对象是代理类
* no-proxy:这种懒加载特性需要对类进行增强,使用no-proxy,其关联对象不是代理类


3.  左外连接检索策略
默认, 在多对一关联级别使用左外连接检索策略
如: <many-to-one outer-join=“true” >
Order order = (Order)session.get(Order.class, 1);
Hibernate执行:
select * from ORDERS left outer join CUSTOMERS on ...

***********************************
Hibernate 允许在应用程序中覆盖映射文件中设定的检索策略, 由应用程序在运行时决定检索对象图的深度.
// 将使用映射文件配置的检索策略
from Customer as c where c.id=1
// 在HQL中显示指定左外连接检索关联的Orders集合, 因此会覆盖映射文件配置的检索策略 
from Customer as c  left join fetch c.orders where c.id=1

Hibernate API: SchemaExport  
方法: create
SchemaExport export = new SchemaExport(new Configuration().configure());
export.create(true, true);


三、抓取 fetch
1. 单端代理的批量抓取
实例A引用实例B,B如果是代理的话,如果遍历A的查询结果集(假如10条),在遍历A的时候访问B变量,将会导致n次查询语句的发出!这个时候,如果B端的class上配置 batch-size,Hibernate会减少SQL语句的数量
批量抓取是延迟查询抓取的优化方案:类级别和集合级别

<many-to-one ... fetch="select | join">

A   select:
关联对象或集合单独执行SQL查询
B    join:  
查询实体使用外连接加载关联的实体或集合,此时 lazy 失效

2. 集合批量抓取
<set ... fetch="select | join | subselect">
select, join 和前面一样, 只影响 load / get
subselect , 影响HQL, 单独发SQL查询HQL查到的所有实体关联的每个集合

四、 批量更新
jdbc fetch size: 每次取多少条数据,需要JDBC和底层数据库的支持,查询大量数据时,不会一次性把全部数据读入内存: hibernate.jdbc.fetch_size建议值50

jdbc batch size: 批量更新,hibernate.jdbc.batch_size建议值30
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!