帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程
EJB 最佳实践:用值对象加速您的 RMI 事务
作者:未知 发布时间:2005-03-12 来源:JSP天空网
保持 EJB 技术的所有优点而不增加 RMI 开销
级别:中级


Brett McLaughlin(brett@oreilly.com)
作家兼编辑,O´Reilly & Associates
2002 年 11 月

EJB 组件的一个比较常见的用途是在关系型数据管理领域。与 RMI 结合起来,EJB 组件让您不必钻研 JDBC 就可以从关系数据库访问数据。但这种抽象是要付出代价的:RMI 很慢,通常是极慢。那么,窍门就是找到一种方法来保持 EJB 技术的所有优点而又没有使用 RMI 的巨大开销。在这篇技巧文章中,您将看到值对象(也称为对象映射)是如何帮助您绕开最严重的 RMI 速度障碍的。您将首先从一个工作示例开始,然后了解代码是怎样工作的。
简单实体 bean
考虑一个名为 DVDs 的简单数据库表。这个表有几列:id、title、releaseDate、producer(通过外键)和 director(也是通过外键)。因为我们正在使用 EJB 组件,所以表由实体 bean 表示,并且每个列都有其自己的取值(accessor)方法和赋值(mutator)方法。清单 1 显示了我们的 DVD 表的远程接口:

清单 1. DVD 远程接口
import com.ibm.ejb;

import java.rmi.RemoteException;
import java.util.Date;
import javax.ejb.EJBObject;

public interface DVD extends EJBObject {

public int getId() throws RemoteException;

public String getTitle() throws RemoteException;
public void setTitle(String title) throws RemoteException;

public Date getReleaseDate() throws RemoteException;
public void setReleaseDate(Date releaseDate) throws RemoteException;

public Person getProducer() throws RemoteException;
public void setProducer(Person producer) throws RemoteException;

public Person getDirector() throws RemoteException;
public void setDirector(Person director) throws RemoteException;
}




这里的问题是如何访问表数据,可能一次访问所有数据。为进行一次 DVD 销售或搜索,在线商店或清单应用程序很可能要求获取上述列中包含的大多数或所有信息。为了访问所有信息,应用程序为每列调用一个取值方法 ? 共有五次方法调用,每次都会多占用一点 RMI 通信时间。这种情况再加上其它复杂性,如可能的错误情况、网络流量和相关问题,以及数据的指数级数量(大多数此类表有 15 行或更多),我们的应用程序随时都可能崩溃。

这时就需要值对象。值对象是简单的 Java 类,可以用它来表示多种对象,包括关系数据库行中的数据。通过直接使用值对象,而不是反复使用 bean 的远程接口,我们可以将 RMI 通信减少到一次方法调用。

创建值对象
清单 2 中的值对象看起来和我们的远程接口几乎相同,但它实际上是具体类。注:通常用 bean 的名称加上 Info 来表示值对象。

清单 2. DVD 值对象
package com.ibm.ejb;

import java.io.Serializable;
import java.util.Date;

public class DVDInfo implements Serializable {

private int id;
private String title
private Date releaseDate;
private Producer producer;
private Director director;

public int getId() {
return id;
}

void setId(int id) {
this.id = id;
}

public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}

public Date getReleaseDate() {
return releaseDate;
}
public void setReleaseDate(Date releaseDate) {
this.releaseDate = releaseDate;
}

public Person getProducer() {
return producer;
}
public void setProducer(Person producer) {
this.producer = producer;
}

public Person getDirector() {
return director;
}
public void setDirector(Person director) {
this.director = director;
}
}




您应该看出这个类的两个特点。首先,它实现了 java.io.Serializable。任何可以被实体 bean(或任何其它 EJB 组件)返回的对象都必须满足这个要求。其次,该类中没有方法能够抛出 RMI RemoteException。这个对象不需要 RMI 通信(这是本练习的全部要点!),因此不会发生 RemoteException。否则,值对象就成为 bean 的远程接口的翻版了。

添加两个新方法
创建值对象类是我们的 RMI 解决方案的第一个部分。第二个部分是将两个有价值的方法添加到我们的远程接口,如清单 3 所示:

清单 3. 已修改的 DVD 远程接口
import com.ibm.ejb;

import java.rmi.RemoteException;
import java.util.Date;
import javax.ejb.EJBObject;

public interface DVD extends EJBObject {

public DVDInfo getInfo() throws RemoteException;
public void setInfo(DVDInfo info) throws RemoteException;

public int getId() throws RemoteException;

public String getTitle() throws RemoteException;
public void setTitle(String title) throws RemoteException;

public Date getReleaseDate() throws RemoteException;
public void setReleaseDate(Date releaseDate) throws RemoteException;

public Person getProducer() throws RemoteException;
public void setProducer(Person producer) throws RemoteException;

public Person getDirector() throws RemoteException;
public void setDirector(Person director) throws RemoteException;
}




接下来,也是最后一步,在我们的 bean 的实现类中实现 getInfo() 和 setInfo() 这两个新方法,如清单 4 所示:

清单 4. 已修改的 DVD 远程接口
// Rest of class excluded for brevity
public DVDInfo getInfo() throws RemoteException {
DVDInfo info = new DVDInfo();

// Load value object with current variable values
info.setId(this.id);
info.setTitle(this.title);
info.setReleaseDate(this.releaseDate);
info.setProducer(getProducer());
info.setDirector(getDirector());

return info;
}

public void setInfo(DVDInfo info) throws RemoteException {
setTitle(info.getTitle());
setReleaseDate(info.getReleaseDate());
setProducer(info.getProducer());
setDirector(info.getDirector());
}




“魔术”是如何实现的
我们的应用程序需要能够访问来自 DVDs 表的 DVD bean 中的所有数据。但是,我们并不调用所有的五个取值方法,而是设置应用程序,只调用一个方法:getInfo()。这大大减少了我们的 RMI 通信。

bean 的实现类在“幕后”调用所有相同的取值方法。但是,因为它们在 EJB 容器中发生,所以它们是本地调用。但是,所有数据仍将传到 bean 客户机,因此仍可以使用这些数据。如果需要对数据进行任何修改,我们可以仅用 setInfo() 方法将它们传回 bean,而不是使用四个或五个开销很大的 RMI 调用。

这种方法唯一的缺点是:有获得旧数据的轻微的风险。如果在内存中将值对象保持一段时间,您就会冒这种风险。虽然值对象包含数据库中数据的快照,但它不能动态地反映数据的更改。避免旧数据的最佳方法是立即使用值对象;如果稍后您需要再次使用它,则应该花一次 RMI 开销来再次调用 getInfo(),以确保可以使用最新数据。

在您的 EJB 应用程序中使用值对象可以产生极大的性能优势,在具有多个取值方法的 bean 中尤其是如此。我的下一篇技巧文章将以和本文相似的风格,着重讨论在结合 EJB 组件使用 JNDI 时减少性能开销。到那时,我将在网上与您见面。

参考资料



对于一切与 EJB 技术相关的事情,Sun Microsystems 的 EJB 主页是很好的参考资料。


The Server Side 提供了许多关于 J2EE 的文章和信息。


教程 EJB fundamentals(developerWorks)提供了对 Enterprise JavaBeans 技术的全面介绍,并特别关注了 EJB 组件在分布式计算环境中所起的作用、体系结构、扩展 API 以及使用 EJB 技术的基础。


访问 developerWorks Java 教程页面以获得其它免费的 Java 技术相关的教程清单。


您可以在 developerWorks Java 技术专区找到关于 Java 编程的各个方面的数百篇文章。

关于作者
Brett McLaughlin 是当今企业编程领域的主要权威之一。他在 Nextel Communications 和 Allegiance Telecom, Inc. 设计、规划和实现过企业解决方案,并协助开发了 Lutris Enhydra 开放源码 J2EE 应用程序服务器。他编写过关于 XML、Java、数据绑定和企业应用程序的书籍,并撰写过 50 多篇关于企业编程的文章。此外,Brett 还是现今可用的每种开放源码 J2EE 应用程序服务器(JBoss、Enhydra 和 OpenEJB)的负责成员。他还是用于 Java 和 XML 的 JDOM API 和 Apache Turbine 项目的共同创始人,并参与了许多其它开放源码项目。他目前为 O´Reilly & Associates 撰写和编辑文章,该公司是全球主要的技术出版商。可通过 brett@oreilly.com 与 Brett 联系。 
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·EJB内部资参(4)  (2005-03-12)
 ·EJB内部资参(3)  (2005-03-12)
 ·EJB内部资参(2)  (2005-03-12)
 ·EJB 体系结构的历史和目标  (2005-03-12)
 ·HTTP会话对象 VS 有状态EJB  (2005-03-12)
 ·五个反对向.NET移植Java EJB应用  (2005-03-12)
 ·EJB 最佳实践:数据验证出现在什  (2005-03-12)
 ·EJB最佳实践:动态委派  (2005-03-12)
 ·JavaBean与EJB有何不同  (2005-03-12)
 ·EJB中Session Bean的见解  (2005-03-12)

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·DiscuzX2.5会员整合通行证发布
·帝国CMS 7.0版本功能建议收集
·帝国网站管理系统2012年授权购买说
·PHPWind8.7会员整合通行证发布
·[官方插件]帝国CMS-访问统计插件
·[官方插件]帝国CMS-sitemap插件
·[官方插件]帝国CMS内容页评论AJAX分
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统