您的位置:首页 > 其它

Hibernate 检索策略

2016-04-11 20:54 405 查看
检索策略

1 概述

在查询数据库时,通常可以从两个方面提升程序的性能:

①节约内存空间

当应用程序需要读取Customer对象的数据并从数据库中将Customer对象加载到内存中,如果同时加载所有关联的Order对象的集合,但是又不使用,那么这些关联的Order对象就白白浪费了许多内存空间。

②少发送SQL语句

每发送一次SQL语句就需要获取一个数据库连接,与数据库进行一次完整的交互过程,而访问数据库往往是一个非常耗时的操作,应尽量减少访问数据库的次数。

2 类级别的检索策略:

load()方法的行为

①默认情况下加载对象时使用延迟检索策略,仅返回代理对象

②使用立即检索时,在方法执行时就加载全部数据

< class name ="Customer" table ="CUSTOMERS" lazy ="false">


3 访问n的一端时的检索策略

①默认情况

加载Customer的时候,不会自动立即加载关联的Order集合

②延迟加载

在Customer的set元素内设置lazy=”false”后就会在加载Customer的同时发送加载Order集合的SQL语句。注意:这里虽然使用了立即加载策略但是并没有合并成一条SQL语句,而是使用了两条SQL语句

延迟检索的SQL

Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_0_,
customer0_.CUST_NAME as CUST_NAM2_0_0_
from
CUSTOMERS customer0_
where
customer0_.CUST_ID=?


在访问Order集合的数据之前

Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK=?
ORDER01
ORDER02


在访问Order集合的数据之后

立即检索的SQL

Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_0_,
customer0_.CUST_NAME as CUST_NAM2_0_0_
from
CUSTOMERS customer0_
where
customer0_.CUST_ID=?
Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK=?


在访问Order集合的数据之前

ORDER02

ORDER01

在访问Order集合的数据之后

③增强的延迟加载

使用lazy属性的extra值表示进一步推迟将数据加载到内存的时机,例如:查询关联的集合的长度时,只发送一条count函数SQL语句

Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_0_,
customer0_.CUST_NAME as CUST_NAM2_0_0_
from
CUSTOMERS customer0_
where
customer0_.CUST_ID=?
Hibernate:
select
count(ORDER_ID)
from
ORDERS
where
CUST_ID_FK =?
2


④batch-size

使用set元素的batch-size属性可以设置在内存中一次性初始化关联的Order集合的个数,减少发送SQL语句的次数。例如:内存中有5个Customer,batch-size=2

【注意:当lazy=时,batch-size设置无效】

Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_,
customer0_.CUST_NAME as CUST_NAM2_0_
from
CUSTOMERS customer0_
customer的个数:5
Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK in (
?, ?
)


order集合长度:2

order集合长度:3

Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK in (
?, ?
)
order集合长度:1
order集合长度:1
Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK=?
order集合长度:0


⑤set元素的fetch属性

[1]select:默认值

[2]subselect:忽略batch-size的设置,以子查询的方式加载全部的Order集合。

Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_,
customer0_.CUST_NAME as CUST_NAM2_0_
from
CUSTOMERS customer0_
customer的个数:5
Hibernate:
select
orderset0_.CUST_ID_FK as CUST_ID_3_0_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_1_,
orderset0_.ORDER_ID as ORDER_ID1_1_0_,
orderset0_.ORDER_NAME as ORDER_NA2_1_0_,
orderset0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS orderset0_
where
orderset0_.CUST_ID_FK in (
select
customer0_.CUST_ID
from
CUSTOMERS customer0_
)


order集合长度:2

order集合长度:3

order集合长度:1

order集合长度:1

order集合长度:0

[3]join时:会在加载Customer对象的时候,就“迫不及待”的查询关联的Order集合,这样的检索方式我们在Hibernate中称之为“迫切左外连接”。

注意:取值为join时,会忽略lazy属性的设置。但是fetch=join对HQL查询无效。

4 访问1的一端

①立即检索

在many-to-one元素中设置lazy=”false”

Tip:在many-to-one元素中lazy属性的可选值是:false、proxy、no-proxy,其中默认值是proxy。

Hibernate:
select
order0_.ORDER_ID as ORDER_ID1_1_0_,
order0_.ORDER_NAME as ORDER_NA2_1_0_,
order0_.CUST_ID_FK as CUST_ID_3_1_0_
from
ORDERS order0_
where
order0_.ORDER_ID=?
Hibernate: select customer0_.CUST_ID as CUST_ID1_0_0_, customer0_.CUST_NAME as CUST_NAM2_0_0_ from CUSTOMERS customer0_ where customer0_.CUST_ID=?
ORDER01
CUST01


②迫切左外连接

将fetch属性设置为join即可

Hibernate:
select
order0_.ORDER_ID as ORDER_ID1_1_1_,
order0_.ORDER_NAME as ORDER_NA2_1_1_,
order0_.CUST_ID_FK as CUST_ID_3_1_1_,
customer1_.CUST_ID as CUST_ID1_0_0_,
customer1_.CUST_NAME as CUST_NAM2_0_0_
from
ORDERS order0_
left outer join
CUSTOMERS customer1_
on order0_.CUST_ID_FK=customer1_.CUST_ID
where
order0_.ORDER_ID=?
ORDER01
CUST01


③batch-size

当查询了一组Order,内存中存在多个Customer时,可以在Customer.hbm.xml文件的class元素中设置batch-size属性,决定加载一组Order集合时同时初始化Customer对象的个数。例如:内存中有4个Customer需要初始化,batch-size设置为3时:

Hibernate:
select
order0_.ORDER_ID as ORDER_ID1_1_,
order0_.ORDER_NAME as ORDER_NA2_1_,
order0_.CUST_ID_FK as CUST_ID_3_1_
from
ORDERS order0_
Hibernate:
select
customer0_.CUST_ID as CUST_ID1_0_0_,
customer0_.CUST_NAME as CUST_NAM2_0_0_
from
CUSTOMERS customer0_
where
customer0_.CUST_ID in (
?, ?, ?
)
CUST01
CUST01
CUST02
CUST02
CUST02
CUST03
Hibernate: select customer0_.CUST_ID as CUST_ID1_0_0_, customer0_.CUST_NAME as CUST_NAM2_0_0_ from CUSTOMERS customer0_ where customer0_.CUST_ID=?
CUST04
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: