fetch检索策略用来说明如何把关联对象加载上来!例如使用单独的select语句来加载关联对象;或者使用左外连接加载当前对象和关联对象。
在单边中设置fetch=join时,由于在加载当前对象时会同时加载关联对象,那么就不可能等到使用关联对象时才去加载关联对象。此时Hibernate使用左外连接加载当前对象和关联对象,这会使关联对象的lazy=true失效。
这里我们使用Order和Customer来说明。其中一个Customer中可以有有多个Order,建立相应的实体类和.hbm.xml文件,在Order.hbm.xml中我们把<many-to-one>元素的fetch属性设置为join;
<many-to-one name="customer" column="customerid" fetch="join"/>
下面是加载Order对象的测试代码:
Order o = (Order)session.load(Order.class, 1);
o.getOrderNumber();
Customer c = o.getCustomer();
c.getName();
下面是代码执行结果:
Hibernate: select order0_.id as id1_1_, order0_.orderNumber as orderNum2_1_1_, order0_.customerid as customerid1_1_, customer1_.id as id0_0_, customer1_.name as name0_0_ from orders order0_ left outer join customer customer1_ on order0_.customerid=customer1_.id where order0_.id=?
结果分析:
1.在执行sesseion.load()方法时不会去加载Order对象,更不会加载关联对象Customer。原因是<class>元素的lazy默认为true,只有在使用Order对象时才会加载Order对象
2.在执行o.getOrderNumber()时会使用左外连接加载Order对象,以及Order所关联的Customer对象。原因是<many-to-one>的fetch的值为join。
若此时fetch=select,则此时会输出
Hibernate: select order0_.id as id1_0_, order0_.orderNumber as orderNum2_1_0_, order0_.customerid as customerid1_0_ from orders order0_ where order0_.id=?
Hibernate: select customer0_.id as id0_0_, customer0_.name as name0_0_ from customer customer0_ where customer0_.id=?
3.在执行o.getOrderNumber()时,Hibernate会加载Order对象,但不会加载相关联对象Customer,原因是<many-to-one>元素的fetch属性值为select。
4.在执行o.getCustomer()方法时也不会加载Customer对象,因为这时还没有使用Customer对象。如果Customer对应的<class>元素的lazy=false时,效果就不一样了,在执行o.getOrderNumber()方法时就会使用左外连接加载Order对象,以及关联对象Customer。也就是说,关联对象的类级别lazy=false时,那么fetch的默认值为join。
5.在执行c.getName()时执行一条select语句来加载Customer对象
在集合一端中使用fetch属性,它的可选值为:join、select、subselect三种。默认值为select。
<set>的fetch=select或fetch=join时,基本与<many-to-one>是相同的,但也有一点不同。在单边fetch中,如果关联对象的类级别lazy=false时,那么fetch的默认值为join,但在集合fetch中,fetch的默认值总是select。
当fetch=subselect时,来测试上会的例子,我们会发现这与fetch=select没有任何区别。这是因为subselect只有在使用HQL时才会有效果
String hql = "from Customer c where c.id in (1,2)";
List<Customer> cList = session.createQuery(hql).list();
for(Customer c : cList) {
c.getName();
Set<Order> orders = c.getOrders();
orders.iterator();
}
结果为:
Hibernate: select customer0_.id as id0_, customer0_.name as name0_ from customer customer0_ where customer0_.id in (1 , 2)
Hibernate: select orders0_.customerid as customerid1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.orderNumber as orderNum2_1_0_, orders0_.customerid as customerid1_0_ from orders orders0_ where orders0_.customerid=?
Hibernate: select orders0_.customerid as customerid1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.orderNumber as orderNum2_1_0_, orders0_.customerid as customerid1_0_ from orders orders0_ where orders0_.customerid=?
结果分析:
1.在执行session.createQuery(hql).list()时,会执行一条SQL语句来加载两个Customer对象,但不会加载关联对象;
2. 在每次执行orders.iteraotr()时会执行一条SQL语句来加载当前Customer对象的关联对象。因为一共有两个Customer对象,所以会执行两条加载关联对象的SQL语句。
把<set>元素的fetch设置为subselect,再次执行上面的代码,结果如下:
Hibernate: select customer0_.id as id0_, customer0_.name as name0_ from customer customer0_ where customer0_.id in (1 , 2)
Hibernate: select orders0_.customerid as customerid1_, orders0_.id as id1_, orders0_.id as id1_0_, orders0_.orderNumber as orderNum2_1_0_, orders0_.customerid as customerid1_0_ from orders orders0_ where orders0_.customerid in (select customer0_.id from customer customer0_ where customer0_.id in (1 , 2))
1.在执行session.createQuery(hql).list()时,会执行一条SQL语句来加载两个Customer对象,但不会加载关联对象。这与上面是一样的,没有什么区别
2.在第一次执行orders.iteraotr()时会执行一条子查询的SQL语句,它会一次性的加载当前List中所有Customer对象的关联对象。所以在下一次再执行orders.iteraotr()时就不会再执行SQL语句了
分享到:
相关推荐
hibernate的类级别检索策略和检索策略的lazy、fetch、batch-size属性使用
学习成长路,Hibernate总结: 1.Hibernate入门优缺点、 2.Hibernate的操作CRUD、 3.主键生成机制、 4.持久化对象的状态、 ...8.Hibernate检索策略(fetch抓取策略)、 9.二级缓存、 10.Hbernate的检索方式(HQL语句)
16.6 在应用程序中显式指定迫切左外连接检索策略 16.7 属性级别的检索策略 16.8 小结 16.9 思考题 第17章 Hibernate的检索方式(上) 17.1 Hibernate的检索方式简介 17.1.1 HQL检索方式 17.1.2 QBC...
16.6 在应用程序中显式指定迫切左外连接检索策略 16.7 属性级别的检索策略 16.8 小结 16.9 思考题 第17章 Hibernate的检索方式(上) 17.1 Hibernate的检索方式简介 17.1.1 HQL检索方式 17.1.2 QBC...
16.6 在应用程序中显式指定迫切左外连接检索策略 16.7 属性级别的检索策略 16.8 小结 16.9 思考题 第17章 Hibernate的检索方式(上) 17.1 Hibernate的检索方式简介 17.1.1 HQL检索方式 17.1.2 QBC...
16.6 在应用程序中显式指定迫切左外连接检索策略 16.7 属性级别的检索策略 16.8 小结 16.9 思考题 第17章 Hibernate的检索方式(上) 17.1 Hibernate的检索方式简介 17.1.1 HQL检索方式 17.1.2 QBC...
HQL的多表检索 事务及隔离级别 HQL优化 抓取策略
Hibernate的检索策略: 1. 延迟检索(加载)映射文件中改变lazy a) Lazy的取值: i. Many-to-one 1. false 2. proxy 3. no-proxy ii. set 一对多 1. true 2. false 3. extra 根据对set容器的不同,可以产生...
在后台,它使用Worker和fetch API 将Blob对象检索到主线程,以便由URL API、 FileReader实例等使用... 查看“部分以获取库兼容性。 方法 拿来 此方法获取给定的资源并将其作为Blob对象返回。 它传递了以下参数: ...
* 13.sequence-identity sequence策略的扩展,采用立即检索策略来获取sequence值,需要JDBC3.0和JDK4以上(含1.4)版本 * 例:@GeneratedValue(generator = "paymentableGenerator") * @GenericGenerator(name = ...
书名:《PHP开发实战1200例(第I卷)》(清华大学出版社.潘凯华.刘中华) PDF格式扫描版,全书分为5篇15章,共899页。2011年1月出版。 全书压缩打包成2部分,这是第1部分。 注:本系列图书的第I、II卷再版时均相应改名...
书名:《PHP开发实战1200例(第I卷)》(清华大学出版社.潘凯华.刘中华) PDF格式扫描版,全书分为5篇15章,共899页。2011年1月出版。 全书压缩打包成2部分,这是第2部分。 注:本系列图书的第I、II卷再版时均相应改名...