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依赖信息文件:...
8. **部署与配置**:帮助用户配置Hibernate项目,包括SessionFactory的生成,事务管理等。 Eclipse Hibernate Tools的4.1.1.Final版本于2013年12月发布,这个版本可能修复了一些已知问题,提升了稳定性和性能。对于...
《深入理解Hibernate配置与映射:hibernate-configuration-3.0.dtd与hibernate-mapping-3.0.dtd解析》 在Java世界里,Hibernate作为一款强大的对象关系映射(ORM)框架,极大地简化了数据库操作。而`hibernate-...
hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码 hibernate-jpa-2.1-api-1.0.0.final-sources.jar 源码
《Hibernate Tools更新4.1.1.Final版详解与应用》 Hibernate Tools是开发者在使用Hibernate框架进行Java应用程序开发时的重要辅助工具,它为Eclipse IDE提供了强大的集成支持,包括对象关系映射(ORM)的可视化设计...
hibernate-jpa-2.0-api-1.0.1.Final-sources.jar hibernate jpa 源代码
在本文中,我们将深入探讨`hibernate-commons-annotations-5.0.1.Final.jar`的源码,了解其内部结构和主要功能。 一、元数据注解 HCA的核心在于提供了一系列的注解,如`@Entity`、`@Table`、`@Column`、`@Id`等,...
hibernate-jpa-2.0-api-1.0.1.Final.jar
今天我们要讨论的是Hibernate框架中的一个关键概念——抓取策略,特别是针对"many-to-one"关系的抓取策略。这篇博客将深入剖析这个主题,帮助你更好地理解和应用Hibernate。 Hibernate是Java领域中最流行的对象关系...
Hibernate稳定版(hibernate-release-5.3.23.Final.zip),Hibernate ORM 是一个为应用程序、库和框架提供对象/关系映射 (ORM) 支持的库。它还提供了 JPA 规范的实现,这是 ORM 的标准 Java 规范。
这篇博客"Hibernate学习一--注解方式自动建表"主要探讨了如何使用Hibernate的注解来实现数据库表的自动化创建。 在Java编程中,注解(Annotation)是一种元数据,它提供了在代码中插入信息的方式,这些信息可以被...
2. **库文件**:包含jar包,如hibernate-core.jar、hibernate-entitymanager.jar等,这些是我们在项目中引入Hibernate时需要用到的依赖库。 3. **文档**:通常包括用户指南、API文档、开发者文档等,这些文档提供了...
本篇主要关注的是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稳定版(hibernate-release-5.6.2.Final.zip),Hibernate ORM 是一个为应用程序、库和框架提供对象/关系映射 (ORM) 支持的库。它还提供了 JPA 规范的实现,这是 ORM 的标准 Java 规范。
`hibernate-core-1a8aca9.ta`是Hibernate的核心组件,它包含了实现ORM功能的关键模块,是学习和开发过程中不可或缺的部分。 一、Hibernate概述 Hibernate是一个开源的ORM框架,它的主要任务是将Java对象与关系型...
hibernate-commons-annotations-5.1.0.Final.jar
hibernate-commons-annotations-4.0.1.Final.jar