懒对象加载模式

原创 2007年09月20日 21:37:00
 
问题
随着轻量级持久化框架的流行(如:Hibernate,JDO,JPA),领域对象取代了传统的DTO直接作为值对象,而在这种架构应用的开发过程中,开发人员常会遇见这样的异常LazyInitializationException。上述问题是由于Hibernate对于领域对象的关系域对象采取了懒加载策略所导致的(即在关系域被访问时才真正加载创建这些相关对象,Hibernate提供的懒加载策略在很多时候都可以让我的程序获得更高的效率);由于领域对象在脱管的状态下被作为值对象传回显示层,而显示层如果访问了采用懒加载策略加载的关系域,便会导致LazyInitializationException异常。
为了避免这个问题,我们常常会在Façade层的业务方法中加入与特定显示要求相绑定的返回对象初始化过程(即装载那些被懒加载了的关系域对象)。Façade通常是我们用于控制事务边界和完成返回的领域对象脱钩的地方。
1 表现层是易变的这样就会导致连锁反应,大量的代码需要维护,完全违背了面向对象设计的原则,增加了程序的维护成本。
2 并且Façade可能用于支持多种不同的表现层,很难让一个方法满足不同的要求。
OSIV(Open Session in View)结构是一种解决上述问题的方法,这种结构之所以能解决上述问题关键就在于OSIV在表现层中控制Session的打开和关闭,控制事务边界。OSIV虽然简化了应用程序的结构,也避免了LazyInitializationException问题,但是也有很多不足:1.增加了表示层的负责度,2.在响应返回表示层前必须提交事务。3.由于减少了封装层次,表现层直接操作领域对象使得包括性能方面的各种优化更为困难。
解决方案
思考既然表示层知道要显示的信息,即领域对象应该加载哪些相关联的对象。那么我们何不把这个任务交给Façade的调用者(表现层)来完成呢?
不同的表示层可能会有不同的显示策略,利用策略模式(GoF)我们让表示层来注入所需的关系域加载策略实现。
下面便是这个想法的实现:
示例中的领域模型:

 

图表 1 示例中领域对象模型
 
示例中相关的组件

图表 2 示例相关组件
LazyObjectLoader:懒对象加载者接口,其定义如下
来对象加载策略接口
package org.ccsoft;
 
publicinterface LazyObjectLoader {
    publicvoid loadLazyObjects(Object obj);
}
该接口定义了不同懒对象加载策略实现者要实现的方法,在loadLazyObjects方法中实现对领域对象obj相关的关系域对象进行加载的策略。
OrderItemLoader一种加载策略的实现,用于加载Order对象的关系域对象OrderItem对象
package org.ccsoft;
 
import java.io.Serializable;
 
publicclass OrderItem implements Serializable {
   
    private String detail;
    public String getDetail() {
       returndetail;
    }
    publicvoid setDetail(String detail) {
       this.detail = detail;
    }
   
}
OrderMgrFacadeImp: Façade的实现,可以使POJO也可以使Session Bean
 
package org.ccsoft;
 
publicclass OrderMgrFacadeImp implements OrderMgrFacade {
    private OrderDAO orderDAO;
    public OrderDAO getOrderDAO() {
       returnorderDAO;
    }
    publicvoid setOrderDAO(OrderDAO orderDAO) {
       this.orderDAO = orderDAO;
    }
    public Order getOrder(int orderId, LazyObjectLoader loader) {
       Order order=orderDAO.getOrder(orderId);
       loader.loadLazyObjects(order);
       return order;
    }
   
}
在getOrder方法中我们要求调用者提供了懒对象装载策略的实例用于装载那些调用者要用到的关系域对象。注意该示例是通过spring实现的,利用spring AOP完成事务管理,事务的边界在Façade中方法上,当方法执行结束,事务业务将结束,并且Hibernate会自动关闭session,我们看到getOrder方法中在事务结束前调用了懒对象装载策略,从而按照调用者的要求装载了调用者所需的关系域对象。
该模式的优点
1 将领域对象的处理逻辑与显示层的显示逻辑完全分离,提高了代码的可维护性和可扩展性
该模式的不足
1 要求显示层的开发者,了解懒加载的情况
2 增加了代码的复杂性

 ————————————————————————————————————


SCEA SCBCD MCSD
IBM Certified Specialist RUP
IBM Certified Solution Designer OOA&D UML v2
北京天融信软件架构师
SUN,Microsoft培训中心特邀高端教师
常年提供架构咨询服务
chaocai2001@yahoo.com.cn 010-82776427

懒加载的一些理解

懒加载的理解1、设计一个HMMusicTool类,这个类有个属性musics 2、使用这个类,会涉及到这个类的这个musics属性 “懒加载模式”又叫“懒汉模式”是指当第一次使用到这个属性时才给这...
  • fanyong245758753
  • fanyong245758753
  • 2016年02月13日 20:29
  • 1455

设计模式____单列模式(懒加载,常加载,双检索,线程安全问题)

//简介: 1.保证一个类仅有一个实例,并提供一个访问它的全局访问点。 2.判断系统是否已经有这个单例,如果有则返回,如果没有则创建。 3.这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需...
  • qq827245563
  • qq827245563
  • 2017年05月08日 09:59
  • 346

hibernate延迟加载(懒加载)详解

Hibernae 的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载。Hibernate 通过这种延迟加载来降低系统的内存开销,从而保证 Hib...
  • xuyukun121
  • xuyukun121
  • 2016年04月19日 13:54
  • 2791

lazy(懒加载)模式和异步加载模式详解

说到懒加载,其实就是延迟会再加载,没有想象中的那么神秘,其实我们时刻都在用懒加载,        第一种:简单的延迟创建控件,比如说,创建一个属性变量,我们用get方法来获取生成这个变量就是用到了懒加...
  • baidu_31683691
  • baidu_31683691
  • 2016年07月14日 11:20
  • 7151

spring容器创建对象的时间和懒加载

我们如何判断一个对象是在spring容器启动的时候创建的呢 还是在我们调用这个对象的时候创建的? 在单例的情况下: 在上面一个spring基础(一)中,我们写了如下的测试类: p...
  • csdnliuxin123524
  • csdnliuxin123524
  • 2017年11月03日 22:03
  • 181

什么是hibernate懒加载?什么时候用懒加载?为什么要用懒加载?

所谓懒加载(lazy)就是延时加载,延迟加载。 什么时候用懒加载呢,我只能回答要用懒加载的时候就用懒加载。 至于为什么要用懒加载呢,就是当我们要访问的数据量过大时,明显用缓存不太合适, 因为内存容量有...
  • u014788554
  • u014788554
  • 2015年04月14日 13:59
  • 1714

hibernate笔记: 关于懒加载和load()方法之三

最近面试别人,正好出的笔试题中有道关于Hibernate延迟加载的问题,聊天过程中发现很多人对Hibernate的延迟加载有些理解误区,写些东东在这里,希望对大家有所帮助。 首先是第一个误区:延...
  • bigtree_3721
  • bigtree_3721
  • 2016年02月26日 14:49
  • 971

什么是hibernate懒加载?什么时候用懒加载?为什么要用懒加载?

sss
  • ITdada
  • ITdada
  • 2014年07月01日 19:02
  • 1564

hibernate懒加载特性及hql和dml操作语言简介

在HQL中关键字不区分大小写,但是属性和类名区分大小写,下面介绍各种类型的Hibernate的HQL查询。 1、Hibernate HQL查询:简单属性查询 * 单一属性查询,返回结果集属性列表,元...
  • do_bset_yourself
  • do_bset_yourself
  • 2016年04月07日 11:10
  • 796

Hibernate中的懒加载原理分析

当使用session中的load方法查询数据库中的记录时,我们返回的是一个代理对象,而不是真正需要的那个对象;例如数据库中存有个Student表,我们有cn.binyulan.doman.Studen...
  • a151296
  • a151296
  • 2015年02月07日 23:02
  • 646
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:懒对象加载模式
举报原因:
原因补充:

(最多只允许输入30个字)