`

Hibernate_使用clone解决hibernate延迟加载问题及分析

 
阅读更多

via: http://www.360doc.com/content/09/0810/17/117897_4814382.shtml

 

首先说明一下,hibernate的延迟加载特性(lazy)。所谓的延迟加载就是当真正需要查询数据时才执行数据加载操作。因为hibernate当中支持实体对象,外键会与实体对象关联起来。如果没有这一特性,当查询某一个含有外键的实体对象时,hibernate会把其他实体对象的数据都查询出来。

简单的来说,当你想查询某个对象时,实际上调用了多条查询语句。有了延迟加载特性,就避免了这种情况的发生,当你真正的使用get另外一个实体对象时,才再执行下面一条查询语句。

但有些时候,这个特性却会给我们应用中带来一些问题。

这个问题相信大家并不陌生了,hibernate的延迟加载(lazy)特性的确不错的优点,如果没了这个特性,我相信大家在处理一些外键的对象时会头大起来,因为效率十分的低。甚至很多人都觉得使用jdbc要比hibernate要高效甚至方便得多,而迫使不去使用hibernate。

我想说,没错,使用jdbc在效率上的确可能要快许多,但差距也不会太大的,因为hibernate本身就支持多种查询方式,SQL、HQL、 DetachedCriteria等。而相反的,hibernate在维护性上比jdbc强很多,因为是实体对象的关系。我相信如果您使用过jdbc来实现注册功能的话,会深有体会。

提示session已关闭(no session or session was closed)

触发这个问题的原因在于,hibernate在查询操作完毕的时候会自动的把session关闭掉,为了降低使用的资源。但问题也这样产生了,不要忘了之前所说的hibernate特性,此时再调用get实体方法的时候就会有可能出现这个错误。因为session已经关闭而不能继续执行查询了。

解决思路:

1、关闭延迟加载特性。

操作起来比较简单,因为hibernate的延迟加载特性是在hbm配置里面可控制的。默认lazy="true",具体配置可以查看一下相关文档,就不详细叙述了。
但使用这个解决办法带来的隐患是十分大的。
首先,出现no session or session was closed就证明了您已经在使用外键关联表,如果去掉延迟加载的话,则表示每次查询的开销都会变得十分的大,如果关联表越多,后果也可以想象得到。所以不建议使用这个方法解决。

2、在session关闭之前把我们想要查询的数据先获取了。

首先需要了解一下session什么时候关闭,也就是它的生命周期。通常情况下hibernate会在查询数据关闭session,而使用getHibernateTemplate().get方法查询后会延迟关闭的时间。会在事务结束后才关闭。

使用拦截器(Interceptor)或过滤器(Filter)控制session。

spring为解决hibernate这一特性提供的解决方案,可以有效的控制session生命周期。

使用这两个方法的详细描述就不多介绍了网上也有不少的文章。这里主要是介绍自己的一套方案。

使用CLONE解决延迟加载问题。

使用Interceptor和Filter,弊端是所有session都一概而论了,无论是否需要延迟session关闭都统统把session关闭的时间延迟了。这里带来了一些资源开销的问题,虽然没必要这么钻牛角尖。但也只是继续本着研究的精神吧。这里的影响程度也是有级别的,因为控制在业务层或者是视图层,影响也有不同的。还有的时候会与其他继承冲突,例如又用了spring的security框架,貌似会有些冲突发生。


在这里想了一下有没有更好的解决办法呢?能在我们需要的时候把数据获取掉,而又不会出现session关闭的情况。

这时我想到了两点,第一,findById方法时候的session会延迟。第二,clone方法。

对于第一点,只能使用get方法来实现也不是绝对的,我们也可以使用DetachedCriteria查询。

第二点有些朋友有些疑问或者陌生,稍微讲解一下。

为什么使用clone?

因为在session关闭之前使用get实体获取的对象没错你也可以查询得到,但是session关闭后,这些数据就不能访问了。如果直接赋值结果还是一样的,因为只是址传递,所以我们必须使用clone方法来把获取后的数据做拷贝操作,而必须还是deep clone,shadow clone也是不行的。


具体操作

1、实现Cloneable接口。

因为我们要进行deep clone操作,所以BO对象必须作以下操作。

implements Cloneable

2、重写(override)clone方法。

clone方法默认为

  1. @Override  
  2. protected Object clone() throws CloneNotSupportedException {   
  3.     return super.clone();   
  4. }  

 

要进行deep clone操作必须把protected改为 public,并且把返回的object改为具体的Bean对象。

3、执行clone操作。

首先,前提当然是确保事务结束之前session未被关闭,可以使用get实体的操作。


然后看下面例子

  1. public List<AccAlias> listAccAlias() {   
  2.     List<AccAlias> all = AccAliasDAO.findAll();   
  3.     if (all != null && !all.isEmpty())   
  4.         for (AccAlias accAlias : all) {   
  5.             try {   
  6.                 Mailbox mailbox = accAlias.getMailbox();   
  7.                 if(mailbox!=null){   
  8.                     mailbox = mailbox.clone();   
  9.                     accAlias.setMailbox(mailbox);   
  10.                 }   
  11.             } catch (CloneNotSupportedException e) {   
  12.                 e.printStackTrace();   
  13.             }   
  14.         }   
  15.     return all;   
  16. }  

 

后续问题研究:

姑且作为一个比较非主流的解决方案吧,是否适合还是要看大家需求的,没有一套方案是绝对适合的。


使用clone解决延迟加载的弊端:

1、clone的实际开销。

2、查询方式的依赖性。必须根据ID查询方式来查询实体。而且更可以认为耦合度提高了,因为业务层clone操作有时必须依赖DAO特定的查询方式。


当然这些弊端也幸好仅仅针对使用到需要解决延迟加载的时候触发。

 

分享到:
评论

相关推荐

    J_ILINK USB不识别,固件修复及出现J_ILIN clone提示的解决办法

    在电子开发和嵌入式系统调试中,J-Link是一个非常常见的仿真器和编程器,它使得开发者能够通过USB接口连接到目标设备进行程序下载、调试和数据分析。然而,有时用户可能会遇到J-Link USB不被电脑识别或者显示“J_...

    vi.rar_Clone code_Code Clone_vi

    《vi.rar_Clone code_Code Clone_vi》是一个关于代码克隆的项目,主要包含了一个名为"vi.c"的小型源代码文件,它是一个针对Linux操作系统的简单`vi`编辑器的克隆实现。在这个项目中,我们将深入探讨代码克隆的概念、...

    PHP编程中的__clone()方法使用详解

    当使用 `clone` 关键字复制一个对象时,系统会创建一个新的对象实例,通常被称为浅拷贝,这意味着原始对象的所有属性都会被复制到新对象中。但是,`__clone()` 方法允许开发者在克隆过程中进行自定义操作,例如修改...

    JINGLING.rar_Code Clone

    标题 "JINGLING.rar_Code Clone" 暗示我们正在处理一个关于代码克隆的项目,其中包含了对名为 "zhangbin-iecas-jingling" 的仓库的复制品。这个仓库最初可能托管在Google Code上,但现在我们拥有的是一个经过压缩的...

    ScrewTurnWiki-2.0.33-Source.zip_Clone code_Code Clone_wiki CShar

    标签"clone_code"和"code_clone"进一步强调了ScrewTurn Wiki与MoinWiki之间的关系,可能是在技术实现上有所借鉴。"wiki_csharp_"则明确了主要编程语言是C#,这是ASP.NET框架的主要开发语言。 根据压缩包子文件的...

    PHP面向对象程序设计之对象克隆clone和魔术方法__clone()用法分析

    当使用`clone`关键字时,PHP会创建一个现有对象的新实例,这个新实例与原对象具有相同的属性和方法。然而,它们之间是独立的,修改其中一个不会影响另一个。例如,如果我们有一个`Person`类,通过`clone`关键字创建...

    midi-ch-master_hero_clone_

    标题 "midi-ch-master_hero_clone_" 暗示了这是一个与音乐游戏Clone Hero相关的项目,其中可能包含用于将MIDI文件转换为Clone Hero可读图表的工具或资源。Clone Hero是一款吉他英雄风格的游戏,允许玩家使用自定义...

    jlink v9 warning clone解决

    总的来说,解决`jlink v9 warning clone`问题需要对硬件、软件和开发环境有深入理解,通过排查硬件、更新固件和驱动、检查配置,以及参考社区经验,通常能有效解决问题。在处理这类问题时,耐心和细致是必不可少的,...

    Jlink-clone解决办法,替换文件.rar

    同时,查阅官方文档和社区论坛,看是否有其他用户遇到类似问题及解决办法。 总之,解决Jlink-clone问题的关键在于识别和替换问题组件。通过替换驱动和固件,我们可以优化克隆设备的性能,使其更接近原版J-Link的...

    SDL plugin for C4droid_3.1_clone.apk

    SDL plugin for C4droid_3.1_clone.apk

    List Clone.zip_c list深度复制_list clone_list的深度复制 C#

    List的深度复制 浅谈C#中List&lt;T&gt;对象的深度拷贝问题

    [高德地图共存]Auto_6.5.0.601323_release_signed_clone.apk

    [高德地图共存]Auto_6.5.0.601323_release_signed_clone.apk

    Shopify_LandingPage_Clone-源码.rar

    Shopify Landing Page Clone 是一个基于Shopify平台的模板项目,其源码被压缩在名...总的来说,Shopify Landing Page Clone 源码提供了一个学习和实践Shopify主题开发的好机会,同时也为电商网站提供了定制化解决方案。

    微微_冰凝海域_clone.apk

    微微_冰凝海域_clone.apk

    JY_MD070_Clone环境alert设置

    文档还包含了遗留问题和已结问题两个章节,其中遗留问题列出了一些尚未解决的技术挑战或待改进的地方,而已结问题则记录了解决的问题和采取的措施。这些记录有助于跟踪问题解决的进度,同时为未来可能遇到类似问题时...

    修改过地址的J-link_v8.bin,完美解决上电clone问题

    已经修改过固件的偏移地址,上电后 mdk会升级,正常现象,让他升级好了,不会有问题,升级完就可以正常使用了. 具体原因如下:由于固件的原因,Jlink一插上电脑就提示Jlink是clone,后来发现J-link_v8.bin这个固件还需要...

    MT管理器_2.14.5-clone.apk

    MT管理器_2.14.5-clone.apk

Global site tag (gtag.js) - Google Analytics