`
gaowenming
  • 浏览: 166723 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

一对一延迟加载问题探讨

阅读更多

JPA定义实体之间的关系有如下几种:

在定义它们的时候可以通过fetch属性指定加载方式,有两个值:

FetchType.LAZY:延迟加载 FetchType.EAGER:急加载

急加载就好理解了,在加载一个实体的时候,其中定义是急加载的的属性(property)和字段(field)会立即从数据库中加载 开发过程中遇到问题最多的就是延迟加载,并且问题都是一个:

“为什么我定义为延迟加载了,但没起作用,相关的属性或者字段还是会立即加载出来?”

对于这个问题,我的理解是这样的,我们首先假设有如下的影射关系:

表的关系是:orders表是一个单独的表,order_items表有一个外键(order_id)引用到orders表,order_finance 有一个外键(order_id)引用到orders表. order_items------->orders<------------order_finance

customer

现在的问题就是:
Order.lineItems 这个@OneToMany的LAZY延迟加载是起作用 的,find order的时候没有find出lineItems
Order.customer 这个@OneToMany的LAZY延迟加载是起作用 的,find order的时候没有find出Customer
Order.salePrice 这个@OneToOne的LAZY延迟加载没起作用 ,find order后会把相关的OrderPrice也fetch 出来
LineItem.order 这个@ManyToOne的LAZY延迟加载是起作用 的,find lineitem没有把相关的order find出来
OrderPrice.order 这个@OneToOne的LAZY延迟加载没起作用 ,find orderprice的时候把相关的order find出来了

延迟加载,顾名思义,就是在访问具体的属性时才从数据库中加载,比如例子中,只有调用OrderPrice.getOrder()的时候才应该会加载 Order这个实体,加载OrderPrice的时候是不应该加载Order的。

那么首先想想,对于延迟加载,hibernate怎么知道什么时候会调用到相关的实体的get方法呢?
答案是它不知道,hibernate不知道什么时候会调用到相关的get方法,那么hibernate如何实现只有访问到才加载这一点? hibernate使用了代理(Proxy),对实体的调用会被代理接受和处理,hibernate可以设置这个代理被调用到的时候去加载数据,从而实现 延迟加载。那么对于一个映射对象,要么它有值,要么它是null,对于null值建立代理是没多大作用的,而且也不能对null建立动态代理。那就是说 hibernate在对延迟加载建立代理的时候要考虑这个映射的对象是否是null。如果是null不需要建立代理,直接把映射的值设置成null,如果 映射的对象不为null,那么hibernate就建立代理对象

延迟加载失败都是由于确定映射的内容是否是null引起的 先来看@OneToMany,比如例子中的Order.lineitems,这是一个Collection,hibernate在加载Order的时候不 加载lineitems,而是创建一个代理(Proxy)一个针对Collection的代理(通常是org.hibernate.collection.persistentBag 。除非你调用了像 Order.getLineItems.size()或者Order.getLineItems.get()方法的时候hibernate才会去加载这个 order的lineitems数据,要不然只是调用Order.getLineItems是不会加载到数据的,因为这个时候并没有具体的访问 LineItem. 由于代理是针对Collection建立的,而不是针对实体建立的,hibernate不用太多考虑是否为null,如果lineitem没有,也只是代 表这个集合是长度是0,这个集合是不为Null的。所以这很容易实现延迟加载

现在在来看例子@OneToOne Order.salePrice。它为什么会失败呢? hibernate也会建立代理,但这个代理是针对OrderPrice建立的(如果延迟加载成功,这个代理类形如 Customer_javasisst_$1) ,默认optioanl=true,也就是说OrderPrice可以为 null,那么hibernate就要考虑,这里是放一个null呢?还是放一个代理。但在Order这个实体里是不能确定它有没有价格的(但在价格里知 道他的Order,有个外键指向order),所以hibernate要确认这个OrderPrice是否存在,这个确认就导致的延迟加载失败,因为 OrderPrice要被查询一次,如果不存在映射值为null,如果存在这个时候值都取出来了,当然就不用什么代理了

Order.customer延迟加载是成功的,order表有一个外键关联到customer表,hibernate应该从这里知道这个 customer是确实存在的,不用把映射值设置成null了,可以设置成代理类Customer_javasisst_$2

那如果把Order.salePrice的映射定义修改成:
@OneToOne(cascade={CascadeType.REMOVE},fetch=FetchType.LAZY,optional=false ,mappedBy="order") @JoinColumn(name="order_id")
private OrderPrice salePrice;
延迟加载就成功了,因为optional=false 指 定salePrice不是可选的,必须有值,所以hibernate也不用考虑是该放null还是放代理,既然必须有值,又是延迟加载,那就设置成代理类 了

根据上面所说的,OrderPrice定义有一个外键关联到Order,那OrderPrice.order这个延迟加载应该是成功的,但为什么会失败 呢? 难道是Order与OrderPrice两边都定义了OneToOne关系? 我这个例子中,这里失败我想是因为OrderPrice这个实体的定 义:@AttributeOverride(name="id",column=@Column(name="order_id"))

再来看看ManyToOne的LineItem.order,这个延迟加载也是成功的。因为lineitem定义了外健关系到order 对于延迟加载的对象,如果已经脱离了容器,调用会得到org.hibernate.LazyInitializationException: could not initialize proxy - no Session方法异常

还有一种情况下延迟加载“看起来是没起作用的”:其实是起作用的,但可能在什么地方的代码调用到了相关的get方法,把延迟加载的对象加载出来的,所以看 起来是没有成功的

总结:

  • 对于延迟加载,hibernate无法知道什么时候会调用到延迟加载的属性/字段的get方法,所以对于延迟加载的属性/字段,hibernate会通过 建立代理Proxy来包装(Wrapper)一下
  • 代理可能会根据实体本身建立,也可以是根据一个集合建立,如果是根据一个集合建立,延迟加载一般都能成功,如果是根据实体建立,null是不能建立代理 的,如果能够确定代理类一定存在,那延迟加载就能成功,相关的映射放置的是代理类,如果不能确定映射的属性是否存在,那就会去数据库中进行查询,这就导致 的延迟失败。 外键定义可以让hibernate知道映射的属性是否存在 也可以通过optional=false来告诉hibernate,映射的属性一定存在
分享到:
评论
3 楼 icantforget 2011-12-12  
有问题啊  optional=false 强制生成对象? 延迟加载?那你的id是怎么来的?
2 楼 gaowenming 2011-07-23  
liguirong98 写道
学习了,但如果该属性确定可能为空呢?那不能设optional=false,怎么办呢?

那就optional=true, 表示该属性可能为空,那就无法延迟加载了,在查询的时候就会去确定该属性的值!
1 楼 liguirong98 2011-07-22  
学习了,但如果该属性确定可能为空呢?那不能设optional=false,怎么办呢?

相关推荐

    mybatis延迟加载样例

    例如,对于一个一对多的关系,我们需要在`&lt;collection&gt;`元素中设置`lazyLoadingEnabled="true"`来开启延迟加载。 2. **懒加载的工作机制**:MyBatis通过代理对象实现延迟加载。当我们尝试访问延迟加载的属性时,...

    jquery图片延迟加载

    为了解决这个问题,开发人员引入了“图片延迟加载”技术,jQuery作为一款广泛使用的JavaScript库,提供了实现这一功能的强大工具。本文将深入探讨jQuery图片延迟加载的概念、优势以及实现方法。 **一、什么是图片...

    11_JPA详解_JPA中的一对多延迟加载与关系维护.zip

    本资料主要探讨的是JPA中的一对多关系以及延迟加载机制,这两部分是JPA使用中的关键概念。 **一对多关系** 在关系数据库中,一对多关系是最常见的一种关联类型。例如,一个部门可以有多名员工,而每个员工只能属于...

    C#+延时加载另一窗体

    - **延时加载(Lazy Loading)**: 是一种设计模式,旨在推迟对资源的加载,直到真正需要它的时候。这样可以减少程序启动时的内存占用,提高启动速度,尤其适用于大型复杂应用。 - 在C#中,我们可以使用`System....

    【北大青鸟内部教程】jsp中关于Hibernate延时加载的问题

    在Hibernate中,一对多、多对一和多对多关系通常可以配置为延时加载。 在JSP中使用Hibernate,开发者可能会遇到以下几种常见的延时加载问题: 1. **空指针异常**:如果没有正确地处理延时加载,当尝试访问未加载的...

    图片延时加载demo

    在这个“图片延时加载demo”中,我们将深入探讨这一技术的工作原理、实现方式以及其在实际应用中的优势。 一、工作原理 图片延时加载的核心思想是只加载视口内的图片,即用户当前能看到的区域。当用户滚动页面,...

    WPF_MVVM模式延时加载实现

    为了解决这个问题,我们可以利用延时加载(Lazy Loading)策略,只在需要时加载特定的树节点,而不是一次性加载所有数据。这样可以显著减少内存占用,提高程序响应速度。 在WPF中实现延时加载,通常有以下步骤: 1...

    11_传智播客JPA详解_JPA中的一对多延迟加载与关系维护

    综上所述,本教程“11_传智播客JPA详解_JPA中的一对多延迟加载与关系维护”会深入探讨这些概念,并提供实际案例帮助你理解和应用它们。通过学习,你将能更好地掌握JPA在处理复杂关系时的高效技巧。

    Flex 与 Hibernate 的延迟加载问题

    本文将深入探讨几种解决Flex与Hibernate延迟加载问题的方法,并着重讲解使用Gilead的方案。 1. **LCDS的Hibernate Adapter**:Adobe LiveCycle Data Services (LCDS) 提供了一个Hibernate适配器,可以处理延迟加载...

    jquery图片预加载延迟加载

    为了实现这种结合,可以首先预加载一部分重要图片,然后对其他图片应用延迟加载: ```javascript $(document).ready(function() { preloadImages(['path/to/image1.jpg', 'path/to/image2.jpg']); // 预加载关键...

    延时加载+静态资源本地缓存

    而延时加载则能优化页面加载流程,尤其对大型图片集的页面来说效果显著。通过熟练掌握这两项技术并灵活运用,我们可以打造更加高效、响应迅速的Web应用,提供优质的用户体验。在提供的压缩包文件"静态资源本地缓存和...

    仿照手机淘宝网站图片延时加载

    在移动互联网时代,为了优化网页性能和用户体验,"仿照手机淘宝网站图片延时加载"是一种常见的技术策略。淘宝作为电商巨头,其移动端应用在图片处理方面有着独特的优化方案,这种技术被称为“懒加载”(Lazy Loading...

    漂亮的瀑布流+延迟加载

    在本项目中,我们将深入探讨如何通过纯手工实现一个具有延迟加载功能的漂亮瀑布流,以及涉及到的关键技术Bootstrap、jQuery、Masonry、imagesLoaded和Lightbox。 1. **Bootstrap**:Bootstrap是世界上最流行的前端...

    fragment延时加载demo

    通过研究和分析这些代码,开发者可以更好地理解和应用延时加载技术,从而优化自己的Android应用。通过实践这样的示例,可以提升对Fragment生命周期的理解,并掌握如何在实际项目中有效地管理资源和性能。

    jQuery滚动图片延迟加载插件【一个大神写的】

    为了解决这个问题,一种常见的技术是图片延迟加载,也称为懒加载(Lazy Loading)。jQuery作为一个强大的JavaScript库,提供了丰富的插件支持,使得实现图片延迟加载变得非常简单。本文将深入探讨一个由大神编写的...

    UITableView网络图片加载优化 延迟加载

    本篇文章将深入探讨UITableView中网络图片的延迟加载(Lazy Loading)策略以及缓存机制,以实现更优秀的用户体验。 1. **延迟加载(Lazy Loading)**: 延迟加载是一种优化策略,旨在减少不必要的资源加载,提高...

    Hibernate 延迟加载

    - **一对一映射(One-to-One)**:在一对一映射中,可以使用`constrained`属性配合`lazy`属性来实现懒加载。具体而言,当`constrained`属性设置为`true`时,并且`lazy`属性启用,表示该关联将采用懒加载策略。 - **...

    懒加载,滚动窗口加载,延迟加载js,jquery脚本demo

    标签中的“懒加载脚本”和“懒加载代码”指的是实现这种功能的程序代码,通常包括两部分:一是设置初始状态,比如隐藏需要延迟加载的元素;二是监听滚动事件并判断元素是否在视口内,如果在则加载对应的资源。 在...

    js文件 合并 压缩 缓存 延迟加载

    最后,**延迟加载**(也称为懒加载)是一种优化策略,它只在真正需要时才加载资源。对于JavaScript,这意味着可以将非关键脚本放在文档底部,或者使用异步加载(async属性)或延迟加载(defer属性)来避免阻塞页面...

    Hibernate 延迟加载剖析与代理模式应用

    本文将深入探讨Hibernate中的延迟加载机制及其背后的代理模式原理。 #### 二、延迟加载概述 延迟加载是一种用于提高系统性能和响应速度的技术,尤其适用于那些需要处理大量数据的应用场景。其基本思想是在真正需要...

Global site tag (gtag.js) - Google Analytics