Hibernate3定义了以下几种抓取策略:
连接抓取(Joinfetching)-Hibernate通过在SELECT语句使用OUTERJOIN(外连接)来获得对象的关联实例或者关联集合。
查询抓取(Selectfetching)-另外发送一条SELECT语句抓取当前对象的关联实体或集合。这也就是通过外键的方式来执行数据库的查询。除非你显式的指定lazy="false"禁止延迟抓取(lazyfetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
子查询抓取(Subselectfetching)-另外发送一条SELECT语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合。与查询抓取的区别在于它所用的SELECT语句的方式为子查询,而不是通过外连接。除非你显式的指定lazy="false"禁止延迟抓取(lazyfetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句。
批量抓取(Batchfetching)-对查询抓取的优化方案,通过指定一个主键或外键列表,Hibernate使用单条SELECT语句获取一批对象实例或集合。
抓取关联对象的时机上有以下几点:
立即抓取,延迟代理抓取,延迟属性抓取,延迟集合抓取
默认对对象关联是采取延迟加载,普通属性采用立即抓取。
对于延迟加载,需要注意的是,对于延迟对象的使用必须在Session关闭之前进行,否则会报LazyInitalizationException。
对于集合类型的关联,在默认情况下会使用延迟集合加载的抓取时机,而对于返回单值类型的关联在默认情况下会使用延迟代理抓取的抓取时机。
A.应用于对象关联实例(默认是延迟加载,默认fetch="select")
<many-to-onename="......"lazy="true/false"fetch="select"/>
B.应用于对象关联集合(默认是延迟加载,默认fetch="select",默认batch-size="1")
<classname="......"table="......"batch-size="1">
......
<setname="......"lazy="true/false"fetch="select">
......
</set>
</class>
(注意:设置fetch=“join”,会导致lazy失效;抓取粒度batch-size并不是越多越好,其值超过50之后,对性能并没有多大改善反而无谓地消耗内存,一般来说,被关联表数据较少则可设置小一点,3~20,如果比较大则可以设到30~50)
以下用Customer与Order的一个双向一对多例子来使用四种抓取策略看看他们的不同之处;
Customer:
lpublicclassCustomer{
lprivatelongid;
lprivateStringname;
lprivateSet<Order>orders;
l//getter/setter略
l}
Order:
lpublicclassOrder{
lprivatelongid;
lprivateStringname;
lprivateCustomercustomer;
l//getter/setter略
l}
Order的映射文件是不变的:
l<hibernate-mapping>
l<classname="Order"table="Order_Table">
l<idname="id">
l<generatorclass="native"/>
l</id>
l<propertyname="name"length="20"column="Order_Name"/>
l<many-to-onename="customer"class="Customer"lazy="proxy"fetch="select"
lcolumn="Cus_ID"cascade="save-update"/>
l</class>
l</hibernate-mapping>
连接抓取(Joinfetching)
连接抓取,使用连接抓取可以将原本需要查询两次(或多次)表的多次查询整合到只需要一次查询即可完成。举个例子,我们在初始化一个含有一对多关系的Customer与Order的时候,会先查询Customer表,找到需要的Customer,然后再根据Customer.id到Order表中查询将Order集合初始化,那么在此完成初始化则需要发送至少两条SQL语句,而如果使用join查询的话,其会根据需要查询的Customer.id,将Customer表与Order表连接起来进行查询,仅仅一条SQL语句就可以将需要的数据全部查询回来;使用连接抓取的配置文件:
l<hibernate-mappingpackage="com.purking.strategys.endUpOne">
l<classname="Customer"table="Customer_Table"lazy="true">
l<idname="id">
l<generatorclass="native"/>
l</id>
l<propertyname="name"length="20"column="Cus_Name"/>
l<setname="orders"
linverse="true"
lfetch="join"//----Here
l<!--这里关闭懒加载是为了试验明显-->
llazy="false">
l<keycolumn="Cus_ID"/>
l<one-to-manyclass="Order"/>
l</set>
l</class>
l</hibernate-mapping>
我们使用如此查询语句:
Customerc1=(Customer)session.get(Customer.class,11l);
c1.getOrders().size();
Hibernate发出的SQL语句为:
lselect
lcustomer0_.idasid0_1_,
lcustomer0_.Cus_NameasCus2_0_1_,
lorders1_.Cus_IDasCus3_3_,
lorders1_.idasid3_,
lorders1_.idasid1_0_,
lorders1_.Order_NameasOrder2_1_0_,
lorders1_.Cus_IDasCus3_1_0_
lfrom
lCustomer_Tablecustomer0_
lleftouterjoin
lOrder_Tableorders1_
loncustomer0_.id=orders1_.Cus_ID
lwhere
lcustomer0_.id=?
在此,Hibernate使用了leftouterjoin连接两个表以一条SQL语句将Order集合给初始化了;
查询抓取(Selectfetching)
查询抓取,这种策略是在集合抓取的时候的默认策略,即如果集合需要初始化,那么会重新发出一条SQL语句进行查询;这是集合默认的抓取策略,也就是我们常会出现N+1次查询的查询策略;
配置文件:
l<hibernate-mappingpackage="com.purking.strategys.endUpOne">
l<classname="Customer"table="Customer_Table"lazy="true">
l<idname="id">
l<generatorclass="native"/>
l</id>
l<propertyname="name"length="20"column="Cus_Name"/>
l<setname="orders"
linverse="true"
lfetch="select">
l<keycolumn="Cus_ID"/>
l<one-to-manyclass="Order"/>
l</set>
l</class>
l</hibernate-mapping>
查询语句不变,看看Hibernate发出的SQL语句:
lHibernate:
lselect
lcustomer0_.idasid0_0_,
lcustomer0_.Cus_NameasCus2_0_0_
lfrom
lCustomer_Tablecustomer0_
lwhere
lcustomer0_.id=?
lHibernate:
lselect
lorders0_.Cus_IDasCus3_1_,
lorders0_.idasid1_,
lorders0_.idasid1_0_,
lorders0_.Order_NameasOrder2_1_0_,
lorders0_.Cus_IDasCus3_1_0_
lfrom
lOrder_Tableorders0_
lwhere
lorders0_.Cus_ID=?
这就是,重新发出一条SQL语句,初始化了Orders集合;
子查询抓取(Subselectfetching)
子查询抓取,另外发送一条SELECT语句抓取在前面查询到(或者抓取到)的所有实体对象的关联集合.这个理解起来有点糊涂,举个例子:如果你使用Query查询出了4个Customer实体,由于开启了懒加载,那么他们的Orders都没有被初始化,那么我现在手初始化一个Customer的Orders,此时由于我选的是Subselectfetching策略,所以Hibernate会将前面查询到的实体对象(4个Customer)的关联集合(在<setname="orders"fetch="subselect"/>)使用一条Select语句一次性抓取回来,这样减少了与数据库的交互次数,一次将每个对象的集合都给初始化了。
[他是如何这么智能的呢?原来,他是将上一次查询的SQL语句作为这一次查询的SQL语句的where子查询,所以上次查询到几个对象,那么这次就初始化几个对象的集合-----正因为如此,所以subselect只在<set>集合中出现];
配置文件:
l<hibernate-mappingpackage="com.purking.strategys.endUpOne">
l<classname="Customer"table="Customer_Table"lazy="true">
l<idname="id">
l<generatorclass="native"/>
l</id>
l<propertyname="name"length="20"column="Cus_Name"/>
l<setname="orders"
linverse="true"
lfetch="subselect"
llazy="true">
l<keycolumn="Cus_ID"/>
l<one-to-manyclass="Order"/>
l</set>
l</class>
l</hibernate-mapping>
测试的语句有变化:
Listresults=session.createQuery("FromCustomercwherec.idin(11,14,17,20)").list();
//这里的四个id是我数据库中已经准备好的数据
Customerc0=(Customer)results.get(0);
c0.getOrders().size();
这个时候再来看看Hibernate发出了什么样的SQL语句:
lHibernate:
lselect
lcustomer0_.idasid0_,
lcustomer0_.Cus_NameasCus2_0_
lfrom
lCustomer_Tablecustomer0_
lwhere
lcustomer0_.idin(
l11,14,17,20
l)
lHibernate:
lselect
lorders0_.Cus_IDasCus3_1_,
lorders0_.idasid1_,
lorders0_.idasid1_0_,
lorders0_.Order_NameasOrder2_1_0_,
lorders0_.Cus_IDasCus3_1_0_
lfrom
lOrder_Tableorders0_
lwhere
lorders0_.Cus_IDin(
lselect
lcustomer0_.id
lfrom
lCustomer_Tablecustomer0_
lwhere
lcustomer0_.idin(
l11,14,17,20
l)
l)
是不是发出的SQL语句形式与这个抓取策略的名字一样?Hibernate的命名很清晰的;
; fon
分享到:
相关推荐
hibernate-commons-annotations-4.0.1.Final.jar hibernate-core-4.1.12.Final.jar hibernate-ehcache-4.1.12.Final.jar hibernate-entitymanager-4.1.12.Final.jar hibernate-jpa-2.0-api-1.0.1.Final.jar ...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
赠送jar包:hibernate-jpa-2.1-api-1.0.2.Final.jar; 赠送原API文档:hibernate-jpa-2.1-api-1.0.2.Final-javadoc.jar; 赠送源代码:hibernate-jpa-2.1-api-1.0.2.Final-sources.jar; 赠送Maven依赖信息文件:...
hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码 hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码
hibernatetools-Update-4.1.1.zip
Eclipse中Hibernate插件。
Eclipse用于Hibernate框架开发插件,全CSDN最低资源分下载,让你吃上真正的石灰。。。
hibernate-jpa-2.0-api-1.0.1.Final.jar
hibernate-jpa-2.1-api-1.0.0.final.jar.zip,内含hibernate-jpa-2.1-api-1.0.0.final.jar
hibernate-commons-annotations-5.0.1.Final.jar的源码
Hibernate稳定版(hibernate-release-5.3.23.Final.zip),Hibernate ORM 是一个为应用程序、库和框架提供对象/关系映射 (ORM) 支持的库。它还提供了 JPA 规范的实现,这是 ORM 的标准 Java 规范。
Hibernate案例与专题-继承映射策略。详细介绍了Hibernate继承映射策略。
包含hibernate所有所需jar包还有一些其他包日志包、jpa支持包等: 列如:hibernate-core-5.1.0.Final.jar hibernate-ehcache-5.1.0.Final.jar ...hibernate-java8-5.1.0.Final.jar ........ 总共41个
hibernate-jpa-2.1-api-1.0.0.Final.jar官方下载,请放心使用
hibernate many-to-many级联保存,级联更新,级联删除
hibernate映射文件--主键生成策略[参考].pdf
hibernate-jpa-2.0-api-1.0.1.Final-sources.jar hibernate jpa 源代码
hibernate one-to-one 一对一唯一外键关联映射_单向 and 双向
Struts+spring+hibernate学习笔记! - Struts原理与实践
hibernate-configuration-3.0.dtd、hibernate-mapping-3.0.dtd、hibernate.properties(5.0.7)